aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-08-16 10:06:14 +0200
committerMartin Liska <mliska@suse.cz>2022-08-16 10:06:14 +0200
commit091222fb0aaa09dcf90f2bc747f1d8a6a8ef1575 (patch)
tree07de02401c3374395a453724c4163d769c02e644
parentb629a7958faf817ef658e3ce59183bfb9ccefe96 (diff)
parent1c596391e150a6b0c55960c1c1cf1da76ea78230 (diff)
downloadgcc-091222fb0aaa09dcf90f2bc747f1d8a6a8ef1575.zip
gcc-091222fb0aaa09dcf90f2bc747f1d8a6a8ef1575.tar.gz
gcc-091222fb0aaa09dcf90f2bc747f1d8a6a8ef1575.tar.bz2
Merge branch 'master' into devel/sphinx
-rw-r--r--gcc/ChangeLog231
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/analyzer/ChangeLog65
-rw-r--r--gcc/analyzer/analyzer.opt4
-rw-r--r--gcc/analyzer/region-model-impl-calls.cc48
-rw-r--r--gcc/analyzer/region-model.cc426
-rw-r--r--gcc/analyzer/region-model.h3
-rw-r--r--gcc/analyzer/region.cc32
-rw-r--r--gcc/analyzer/region.h4
-rw-r--r--gcc/analyzer/sm-fd.cc13
-rw-r--r--gcc/analyzer/store.cc67
-rw-r--r--gcc/analyzer/store.h9
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-gimplify.cc12
-rw-r--r--gcc/c/ChangeLog9
-rw-r--r--gcc/c/c-parser.cc19
-rw-r--r--gcc/common/config/xtensa/xtensa-common.cc2
-rw-r--r--gcc/config/aarch64/aarch64-sve.md4
-rw-r--r--gcc/config/aarch64/aarch64.md3
-rw-r--r--gcc/config/i386/i386-builtin-types.def1
-rw-r--r--gcc/config/i386/i386-builtins.cc21
-rw-r--r--gcc/config/i386/i386-features.cc167
-rw-r--r--gcc/config/i386/i386-modes.def2
-rw-r--r--gcc/config/i386/i386.cc80
-rw-r--r--gcc/config/i386/i386.h4
-rw-r--r--gcc/config/i386/i386.md45
-rw-r--r--gcc/config/i386/predicates.md8
-rw-r--r--gcc/config/i386/sse.md95
-rw-r--r--gcc/config/rs6000/mma.md39
-rw-r--r--gcc/config/rs6000/rs6000-builtin.cc65
-rw-r--r--gcc/config/rs6000/rs6000-internal.h1
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/decl.cc8
-rw-r--r--gcc/cp/typeck.cc31
-rw-r--r--gcc/d/ChangeLog34
-rw-r--r--gcc/d/d-codegen.cc38
-rw-r--r--gcc/d/d-compiler.cc11
-rw-r--r--gcc/d/d-tree.h2
-rw-r--r--gcc/d/decl.cc22
-rw-r--r--gcc/d/expr.cc2
-rw-r--r--gcc/d/modules.cc20
-rw-r--r--gcc/d/typeinfo.cc4
-rw-r--r--gcc/doc/invoke.texi36
-rw-r--r--gcc/fortran/gfortran.texi6
-rw-r--r--gcc/gcc.cc37
-rw-r--r--gcc/gimple-range-path.cc145
-rw-r--r--gcc/gimple-range-path.h2
-rw-r--r--gcc/gimple-ssa-store-merging.cc2
-rw-r--r--gcc/ifcvt.cc41
-rw-r--r--gcc/ipa-devirt.cc37
-rw-r--r--gcc/lto-wrapper.cc44
-rw-r--r--gcc/lto/ChangeLog8
-rw-r--r--gcc/lto/lto.cc58
-rw-r--r--gcc/match.pd40
-rw-r--r--gcc/opts-common.cc94
-rw-r--r--gcc/opts-jobserver.h60
-rw-r--r--gcc/testsuite/ChangeLog252
-rw-r--r--gcc/testsuite/c-c++-common/Winit-self1.c31
-rw-r--r--gcc/testsuite/c-c++-common/Winit-self2.c31
-rw-r--r--gcc/testsuite/g++.dg/abi/anon1.C1
-rw-r--r--gcc/testsuite/g++.dg/abi/anon4.C2
-rw-r--r--gcc/testsuite/g++.dg/analyzer/out-of-bounds-placement-new.C19
-rw-r--r--gcc/testsuite/g++.dg/analyzer/pr100244.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C63
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-const1.C4
-rw-r--r--gcc/testsuite/g++.dg/init/static-cdtor1.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/loc-prune-4.C4
-rw-r--r--gcc/testsuite/g++.dg/no-stack-protector-attr-3.C1
-rw-r--r--gcc/testsuite/g++.dg/opt/pr94589-2.C2
-rw-r--r--gcc/testsuite/g++.dg/pr104992-1.C2
-rw-r--r--gcc/testsuite/g++.dg/pr71694.C1
-rw-r--r--gcc/testsuite/g++.dg/stackprotectexplicit2.C1
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr101839.C53
-rw-r--r--gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C10
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/allocation-size-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/fd-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c38
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/fd-uninit-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/memcpy-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c120
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c83
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c91
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c51
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-coreutils.c29
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c41
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c54
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c54
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr101962.c6
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr106539.c15
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr96764.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr97029.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/realloc-5.c45
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/test-setjmp.h4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/pr93451.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/zlib-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr102892-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr104992.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr106243-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr106243.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr106621.c30
-rw-r--r--gcc/testsuite/gcc.dg/pr64992.c7
-rw-r--r--gcc/testsuite/gcc.dg/pr71343-1.c56
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-11.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-self.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr106513.c26
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr106590.c75
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-18.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-19.c33
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-20.c15
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr106524.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-dest-false-dep-for-glc.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-7.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/bfloat16-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-11.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-12.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-13.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-15.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-16.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-17.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-8.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pad-10.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100704-3.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-4a.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-4b.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-5a.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-5b.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-6a.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-6b.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-6c.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100865-7b.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101796-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101846-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101989-broadcast-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102021.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr106322.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/pr15184-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr15184-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr27971.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-7.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr70263-2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr70321.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr78035.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81563.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81736-5.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81736-7.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84278.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85620-6.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85667-6.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-17.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-2.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90773-3.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr93492-5.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94913-2.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95126-m32-1.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95126-m32-2.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95852-2.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr95852-4.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96539.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c215
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-stv-9.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/stack-check-12.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/stack-check-17.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/stack-prot-sym.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr103353.c22
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr106322.c50
-rw-r--r--gcc/testsuite/gdc.dg/torture/pr106623.d28
-rw-r--r--gcc/tree-ssa-loop.h10
-rw-r--r--gcc/tree-ssa-phiopt.cc4
-rw-r--r--gcc/tree-ssa-threadbackward.cc117
-rw-r--r--gcc/tree-vect-stmts.cc8
-rw-r--r--gcc/value-range.cc35
194 files changed, 4123 insertions, 469 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9450838..9d4d2e0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,234 @@
+2022-08-15 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/106621
+ * value-range.cc (irange::set): Check for POLY_INT_CST early.
+
+2022-08-15 Roger Sayle <roger@nextmovesoftware.com>
+
+ * config/i386/i386-features.cc
+ (timode_scalar_chain::compute_convert_gain): Provide costs for
+ shifts and rotates.
+ (timode_scalar_chain::convert_insn): Handle ASHIFTRT, ROTATERT
+ and ROTATE just like existing ASHIFT and LSHIFTRT cases.
+ (timode_scalar_to_vector_candidate_p): Handle all shifts and
+ rotates by integer constants between 0 and 127.
+
+2022-08-15 Roger Sayle <roger@nextmovesoftware.com>
+
+ * config/i386/i386-features.cc
+ (timode_scalar_chain::compute_convert_gain): Provide gains for
+ comparisons against 0/-1, including "*testti" patterns.
+
+2022-08-15 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR tree-optimization/64992
+ PR tree-optimization/98956
+ * match.pd (ne (lshift @0 @1) 0): Simplify (X << C) != 0 to X
+ when X is zero_one_valued_p and the shift constant C is valid.
+ (eq (lshift @0 @1) 0): Likewise, simplify (X << C) == 0 to !X
+ when X is zero_one_valued_p and the shift constant C is valid.
+
+2022-08-15 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/71343
+ * match.pd (op (lshift @0 @1) (lshift @2 @1)): Optimize the
+ expression (X<<C) + (Y<<C) to (X+Y)<<C for multiple operators.
+ (op (rshift @0 @1) (rshift @2 @1)): Likewise, simplify (X>>C)^(Y>>C)
+ to (X^Y)>>C for binary logical operators, AND, IOR and XOR.
+
+2022-08-15 Richard Biener <rguenther@suse.de>
+
+ * gimple-range-path.cc (range_on_path_entry): Just
+ call range_on_entry.
+
+2022-08-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/106590
+ * ifcvt.cc (check_for_cc_cmp_clobbers): New function.
+ (noce_convert_multiple_sets_1): If SEQ sets or clobbers any regs
+ mentioned in cc_cmp or rev_cc_cmp, don't consider seq2 for any
+ further conditional moves.
+
+2022-08-15 konglin1 <lingling.kong@intel.com>
+
+ * config/i386/i386-builtin-types.def (BFLOAT16): New primitive type.
+ * config/i386/i386-builtins.cc : Support __bf16 type for i386 backend.
+ (ix86_register_bf16_builtin_type): New function.
+ (ix86_bf16_type_node): New.
+ (ix86_bf16_ptr_type_node): Ditto.
+ (ix86_init_builtin_types): Add ix86_register_bf16_builtin_type function call.
+ * config/i386/i386-modes.def (FLOAT_MODE): Add BFmode.
+ (ADJUST_FLOAT_FORMAT): Ditto.
+ * config/i386/i386.cc (classify_argument): Handle BFmode.
+ (construct_container): Ditto.
+ (function_value_32): Return __bf16 by %xmm0.
+ (function_value_64): Return __bf16 by SSE register.
+ (ix86_output_ssemov): Handle BFmode.
+ (ix86_legitimate_constant_p): Disable BFmode constant double.
+ (ix86_secondary_reload): Require gpr as intermediate register
+ to store __bf16 from sse register when sse4 is not available.
+ (ix86_scalar_mode_supported_p): Enable __bf16 under sse2.
+ (ix86_mangle_type): Add manlging for __bf16 type.
+ (ix86_invalid_conversion): New function for target hook.
+ (ix86_invalid_unary_op): Ditto.
+ (ix86_invalid_binary_op): Ditto.
+ (TARGET_INVALID_CONVERSION): New define for target hook.
+ (TARGET_INVALID_UNARY_OP): Ditto.
+ (TARGET_INVALID_BINARY_OP): Ditto.
+ * config/i386/i386.h (host_detect_local_cpu): Add BFmode.
+ * config/i386/i386.md ("mode"): Add BFmode.
+ (MODE_SIZE): Ditto.
+ (X87MODEFH): Ditto.
+ (HFBF): Add new define_mode_iterator.
+ (*pushhf_rex64): Change for BFmode.
+ (*push<mode>_rex64): Ditto.
+ (*pushhf): Ditto.
+ (*push<mode>): Ditto.
+ (MODESH): Ditto.
+ (hfbfconstf): Add new define_mode_attr.
+ (*mov<mode>_internal): Add BFmode.
+
+2022-08-13 Roger Sayle <roger@nextmovesoftware.com>
+ Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/predicates.md (const_0_to_255_not_mul_8_operand):
+ New predicate for values between 0/1 and 255, not multiples of 8.
+ * config/i386/sse.md (ashlv1ti3): Delay lowering of logical left
+ shifts by constant bit counts.
+ (*ashlvti3_internal): New define_insn_and_split that lowers
+ logical left shifts by constant bit counts, that aren't multiples
+ of 8, before reload.
+ (lshrv1ti3): Delay lowering of logical right shifts by constant.
+ (*lshrv1ti3_internal): New define_insn_and_split that lowers
+ logical right shifts by constant bit counts, that aren't multiples
+ of 8, before reload.
+ (ashrv1ti3):: Delay lowering of arithmetic right shifts by
+ constant bit counts.
+ (*ashrv1ti3_internal): New define_insn_and_split that lowers
+ arithmetic right shifts by constant bit counts before reload.
+ (rotlv1ti3): Delay lowering of rotate left by constant.
+ (*rotlv1ti3_internal): New define_insn_and_split that lowers
+ rotate left by constant bits counts before reload.
+ (rotrv1ti3): Delay lowering of rotate right by constant.
+ (*rotrv1ti3_internal): New define_insn_and_split that lowers
+ rotate right by constant bits counts before reload.
+
+2022-08-12 Srinath Parvathaneni <srinath.parvathaneni@arm.com>
+
+ * doc/invoke.texi (Arm Options): Document -mcpu=cortex-m55 options.
+
+2022-08-12 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/106057
+ * ipa-devirt.cc (type_or_derived_type_possibly_instantiated_p): New
+ function.
+ (possible_polymorphic_call_targets): Use it.
+
+2022-08-12 Andrew Carlotti <andrew.carlotti@arm.com>
+
+ * tree-ssa-loop.h: Improve comment
+
+2022-08-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/106506
+ * tree-ssa-phiopt.cc (spaceship_replacement): Don't punt for
+ is_cast or orig_use_lhs cases if phi_bb has 3 predecessors.
+
+2022-08-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106593
+ * tree-ssa-threadbackward.cc (back_threader::find_paths):
+ If the imports from the conditional do not satisfy
+ gimple_range_ssa_p don't try to thread anything.
+
+2022-08-12 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/106524
+ * config/aarch64/aarch64-sve.md (*fcmuo<mode>_nor_combine,
+ *fcmuo<mode>_bic_combine): Don't accept comparisons against zero.
+
+2022-08-12 Tim Lange <mail@tim-lange.me>
+
+ PR analyzer/106000
+ * doc/invoke.texi: Add Wanalyzer-out-of-bounds.
+
+2022-08-12 Andrew Pinski <apinski@marvell.com>
+
+ * config/aarch64/aarch64.md: Remove comment
+ about MD_INCLUDES as it is out of date and not needed.
+
+2022-08-11 Richard Biener <rguenther@suse.de>
+
+ * gimple-range-path.cc (path_range_query::compute_imports):
+ Restrict walking SSA defs to blocks inside the path. Track
+ the same operands as range_def_chain::get_def_chain does.
+
+2022-08-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106514
+ * tree-ssa-threadbackward.cc (back_threader::find_paths_to_names):
+ Compute and unwind both m_imports and interesting on the fly during
+ path discovery.
+ (back_threader::find_paths): Compute the original m_imports
+ from just the SSA uses of the exit conditional. Drop
+ handling single_succ_to_potentially_threadable_block.
+ * gimple-range-path.cc (path_range_query::ssa_range_in_phi): Handle
+ constant PHI arguments without crashing. Use PHI_ARG_DEF_FROM_EDGE.
+
+2022-08-11 Richard Biener <rguenther@suse.de>
+
+ * gimple-range-path.h (path_range_query::compute_imports):
+ Take path as argument, not the exit block.
+ * gimple-range-path.cc (path_range_query::compute_imports):
+ Likewise, and adjust, avoiding possibly stale m_path.
+ (path_range_query::compute_outgoing_relations): Register
+ relations for all conditionals.
+ * tree-ssa-threadbackward.cc (back_threader::find_paths):
+ Adjust.
+
+2022-08-11 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Fix the
+ oversight on ENB_CELL by simplifying with rs6000_builtin_is_supported.
+ (rs6000_expand_builtin): Simplify with rs6000_builtin_is_supported.
+
+2022-08-11 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/rs6000/rs6000-internal.h (rs6000_global_entry_point_needed_p):
+ Remove function declaration.
+
+2022-08-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106513
+ * gimple-ssa-store-merging.cc (do_shift_rotate): Use uint64_t
+ for head_marker.
+
+2022-08-10 Martin Liska <mliska@suse.cz>
+
+ PR lto/106328
+ * opts-jobserver.h (struct jobserver_info): Add pipefd.
+ (jobserver_info::connect): New.
+ (jobserver_info::disconnect): Likewise.
+ (jobserver_info::get_token): Likewise.
+ (jobserver_info::return_token): Likewise.
+ * opts-common.cc: Implement the new functions.
+
+2022-08-10 Martin Liska <mliska@suse.cz>
+
+ * opts-jobserver.h: Add one member.
+ * opts-common.cc (jobserver_info::jobserver_info): Parse FIFO
+ format of --jobserver-auth.
+
+2022-08-10 Martin Liska <mliska@suse.cz>
+
+ * gcc.cc (driver::detect_jobserver): Remove and move to
+ jobserver.h.
+ * lto-wrapper.cc (jobserver_active_p): Likewise.
+ (run_gcc): Likewise.
+ * opts-jobserver.h: New file.
+ * opts-common.cc (jobserver_info::jobserver_info): New function.
+
2022-08-09 Roger Sayle <roger@nextmovesoftware.com>
* config/i386/i386-features.cc (scalar_chain::convert_compare):
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 9049af1..9e916fe 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20220810
+20220816
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index b16971b..d190956 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,68 @@
+2022-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106626
+ * region-model.cc (buffer_overread::emit): Fix copy&paste error in
+ direction of the access in the note.
+
+2022-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106573
+ * region-model.cc (region_model::on_call_pre): Use check_call_args
+ when ensuring that we call get_arg_svalue on all args. Remove
+ redundant call from handling for stdio builtins.
+
+2022-08-15 Immad Mir <mirimmad@outlook.com>
+
+ PR analyzer/106551
+ * sm-fd.cc (check_for_dup): exit early if first
+ argument is invalid for all dup functions.
+
+2022-08-12 Tim Lange <mail@tim-lange.me>
+
+ PR analyzer/106000
+ * analyzer.opt: Add Wanalyzer-out-of-bounds.
+ * region-model.cc (class out_of_bounds): Diagnostics base class
+ for all out-of-bounds diagnostics.
+ (class past_the_end): Base class derived from out_of_bounds for
+ the buffer_overflow and buffer_overread diagnostics.
+ (class buffer_overflow): Buffer overflow diagnostics.
+ (class buffer_overread): Buffer overread diagnostics.
+ (class buffer_underflow): Buffer underflow diagnostics.
+ (class buffer_underread): Buffer overread diagnostics.
+ (region_model::check_region_bounds): New function to check region
+ bounds for out-of-bounds accesses.
+ (region_model::check_region_access):
+ Add call to check_region_bounds.
+ (region_model::get_representative_tree): New function that accepts
+ a region instead of an svalue.
+ * region-model.h (class region_model):
+ Add region_model::check_region_bounds.
+ * region.cc (region::symbolic_p): New predicate.
+ (offset_region::get_byte_size_sval): Only return the remaining
+ byte size on offset_regions.
+ * region.h: Add region::symbolic_p.
+ * store.cc (byte_range::intersects_p):
+ Add new function equivalent to bit_range::intersects_p.
+ (byte_range::exceeds_p): New function.
+ (byte_range::falls_short_of_p): New function.
+ * store.h (struct byte_range): Add byte_range::intersects_p,
+ byte_range::exceeds_p and byte_range::falls_short_of_p.
+
+2022-08-12 Tim Lange <mail@tim-lange.me>
+
+ PR analyzer/106539
+ * region-model-impl-calls.cc (region_model::impl_call_realloc):
+ Use the result of get_copied_size as the size for the
+ sized_regions in realloc.
+ (success_with_move::get_copied_size): New function.
+
+2022-08-11 Immad Mir <mirimmad@outlook.com>
+
+ PR analyzer/106551
+ * sm-fd.cc (check_for_dup): handle the m_start
+ state when transitioning the state of LHS
+ of dup, dup2 and dup3 call.
+
2022-08-09 David Malcolm <dmalcolm@redhat.com>
PR analyzer/106573
diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index c6d9c53..61b58c5 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -110,6 +110,10 @@ Wanalyzer-mismatching-deallocation
Common Var(warn_analyzer_mismatching_deallocation) Init(1) Warning
Warn about code paths in which the wrong deallocation function is called.
+Wanalyzer-out-of-bounds
+Common Var(warn_analyzer_out_of_bounds) Init(1) Warning
+Warn about code paths in which a write or read to a buffer is out-of-bounds.
+
Wanalyzer-possible-null-argument
Common Var(warn_analyzer_possible_null_argument) Init(1) Warning
Warn about code paths in which a possibly-NULL value is passed to a must-not-be-NULL function argument.
diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc
index 3f821ff..8eebd12 100644
--- a/gcc/analyzer/region-model-impl-calls.cc
+++ b/gcc/analyzer/region-model-impl-calls.cc
@@ -849,15 +849,17 @@ region_model::impl_call_realloc (const call_details &cd)
const svalue *old_size_sval = model->get_dynamic_extents (freed_reg);
if (old_size_sval)
{
- const region *sized_old_reg
+ const svalue *copied_size_sval
+ = get_copied_size (old_size_sval, new_size_sval);
+ const region *copied_old_reg
= model->m_mgr->get_sized_region (freed_reg, NULL,
- old_size_sval);
+ copied_size_sval);
const svalue *buffer_content_sval
- = model->get_store_value (sized_old_reg, cd.get_ctxt ());
- const region *sized_new_reg
+ = model->get_store_value (copied_old_reg, cd.get_ctxt ());
+ const region *copied_new_reg
= model->m_mgr->get_sized_region (new_reg, NULL,
- old_size_sval);
- model->set_value (sized_new_reg, buffer_content_sval,
+ copied_size_sval);
+ model->set_value (copied_new_reg, buffer_content_sval,
cd.get_ctxt ());
}
else
@@ -891,6 +893,40 @@ region_model::impl_call_realloc (const call_details &cd)
else
return true;
}
+
+ private:
+ /* Return the lesser of OLD_SIZE_SVAL and NEW_SIZE_SVAL.
+ If either one is symbolic, the symbolic svalue is returned. */
+ const svalue *get_copied_size (const svalue *old_size_sval,
+ const svalue *new_size_sval) const
+ {
+ tree old_size_cst = old_size_sval->maybe_get_constant ();
+ tree new_size_cst = new_size_sval->maybe_get_constant ();
+
+ if (old_size_cst && new_size_cst)
+ {
+ /* Both are constants and comparable. */
+ tree cmp = fold_binary (LT_EXPR, boolean_type_node,
+ old_size_cst, new_size_cst);
+
+ if (cmp == boolean_true_node)
+ return old_size_sval;
+ else
+ return new_size_sval;
+ }
+ else if (new_size_cst)
+ {
+ /* OLD_SIZE_SVAL is symbolic, so return that. */
+ return old_size_sval;
+ }
+ else
+ {
+ /* NEW_SIZE_SVAL is symbolic or both are symbolic.
+ Return NEW_SIZE_SVAL, because implementations of realloc
+ probably only moves the buffer if the new size is larger. */
+ return new_size_sval;
+ }
+ }
};
/* Body of region_model::impl_call_realloc. */
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 8393c7d..b05b709 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -1268,6 +1268,414 @@ region_model::on_stmt_pre (const gimple *stmt,
}
}
+/* Abstract base class for all out-of-bounds warnings. */
+
+class out_of_bounds : public pending_diagnostic_subclass<out_of_bounds>
+{
+public:
+ out_of_bounds (const region *reg, tree diag_arg,
+ byte_range out_of_bounds_range)
+ : m_reg (reg), m_diag_arg (diag_arg),
+ m_out_of_bounds_range (out_of_bounds_range)
+ {}
+
+ const char *get_kind () const final override
+ {
+ return "out_of_bounds_diagnostic";
+ }
+
+ bool operator== (const out_of_bounds &other) const
+ {
+ return m_reg == other.m_reg
+ && m_out_of_bounds_range == other.m_out_of_bounds_range
+ && pending_diagnostic::same_tree_p (m_diag_arg, other.m_diag_arg);
+ }
+
+ int get_controlling_option () const final override
+ {
+ return OPT_Wanalyzer_out_of_bounds;
+ }
+
+ void mark_interesting_stuff (interesting_t *interest) final override
+ {
+ interest->add_region_creation (m_reg);
+ }
+
+protected:
+ const region *m_reg;
+ tree m_diag_arg;
+ byte_range m_out_of_bounds_range;
+};
+
+/* Abstract subclass to complaing about out-of-bounds
+ past the end of the buffer. */
+
+class past_the_end : public out_of_bounds
+{
+public:
+ past_the_end (const region *reg, tree diag_arg, byte_range range,
+ tree byte_bound)
+ : out_of_bounds (reg, diag_arg, range), m_byte_bound (byte_bound)
+ {}
+
+ bool operator== (const past_the_end &other) const
+ {
+ return out_of_bounds::operator== (other)
+ && pending_diagnostic::same_tree_p (m_byte_bound,
+ other.m_byte_bound);
+ }
+
+ label_text
+ describe_region_creation_event (const evdesc::region_creation &ev) final
+ override
+ {
+ if (m_byte_bound && TREE_CODE (m_byte_bound) == INTEGER_CST)
+ return ev.formatted_print ("capacity is %E bytes", m_byte_bound);
+
+ return label_text ();
+ }
+
+protected:
+ tree m_byte_bound;
+};
+
+/* Concrete subclass to complain about buffer overflows. */
+
+class buffer_overflow : public past_the_end
+{
+public:
+ buffer_overflow (const region *reg, tree diag_arg,
+ byte_range range, tree byte_bound)
+ : past_the_end (reg, diag_arg, range, byte_bound)
+ {}
+
+ bool emit (rich_location *rich_loc) final override
+ {
+ diagnostic_metadata m;
+ bool warned;
+ switch (m_reg->get_memory_space ())
+ {
+ default:
+ m.add_cwe (787);
+ warned = warning_meta (rich_loc, m, get_controlling_option (),
+ "buffer overflow");
+ break;
+ case MEMSPACE_STACK:
+ m.add_cwe (121);
+ warned = warning_meta (rich_loc, m, get_controlling_option (),
+ "stack-based buffer overflow");
+ break;
+ case MEMSPACE_HEAP:
+ m.add_cwe (122);
+ warned = warning_meta (rich_loc, m, get_controlling_option (),
+ "heap-based buffer overflow");
+ break;
+ }
+
+ if (warned)
+ {
+ char num_bytes_past_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (m_out_of_bounds_range.m_size_in_bytes,
+ num_bytes_past_buf, UNSIGNED);
+ if (m_diag_arg)
+ inform (rich_loc->get_loc (), "write is %s bytes past the end"
+ " of %qE", num_bytes_past_buf,
+ m_diag_arg);
+ else
+ inform (rich_loc->get_loc (), "write is %s bytes past the end"
+ "of the region",
+ num_bytes_past_buf);
+ }
+
+ return warned;
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev)
+ final override
+ {
+ byte_size_t start = m_out_of_bounds_range.get_start_byte_offset ();
+ byte_size_t end = m_out_of_bounds_range.get_last_byte_offset ();
+ char start_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (start, start_buf, SIGNED);
+ char end_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (end, end_buf, SIGNED);
+
+ if (start == end)
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds write at byte %s but %qE"
+ " ends at byte %E", start_buf, m_diag_arg,
+ m_byte_bound);
+ return ev.formatted_print ("out-of-bounds write at byte %s but region"
+ " ends at byte %E", start_buf,
+ m_byte_bound);
+ }
+ else
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds write from byte %s till"
+ " byte %s but %qE ends at byte %E",
+ start_buf, end_buf, m_diag_arg,
+ m_byte_bound);
+ return ev.formatted_print ("out-of-bounds write from byte %s till"
+ " byte %s but region ends at byte %E",
+ start_buf, end_buf, m_byte_bound);
+ }
+ }
+};
+
+/* Concrete subclass to complain about buffer overreads. */
+
+class buffer_overread : public past_the_end
+{
+public:
+ buffer_overread (const region *reg, tree diag_arg,
+ byte_range range, tree byte_bound)
+ : past_the_end (reg, diag_arg, range, byte_bound)
+ {}
+
+ bool emit (rich_location *rich_loc) final override
+ {
+ diagnostic_metadata m;
+ m.add_cwe (126);
+ bool warned = warning_meta (rich_loc, m, get_controlling_option (),
+ "buffer overread");
+
+ if (warned)
+ {
+ char num_bytes_past_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (m_out_of_bounds_range.m_size_in_bytes,
+ num_bytes_past_buf, UNSIGNED);
+ if (m_diag_arg)
+ inform (rich_loc->get_loc (), "read is %s bytes past the end"
+ " of %qE", num_bytes_past_buf,
+ m_diag_arg);
+ else
+ inform (rich_loc->get_loc (), "read is %s bytes past the end"
+ "of the region",
+ num_bytes_past_buf);
+ }
+
+ return warned;
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev)
+ final override
+ {
+ byte_size_t start = m_out_of_bounds_range.get_start_byte_offset ();
+ byte_size_t end = m_out_of_bounds_range.get_last_byte_offset ();
+ char start_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (start, start_buf, SIGNED);
+ char end_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (end, end_buf, SIGNED);
+
+ if (start == end)
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds read at byte %s but %qE"
+ " ends at byte %E", start_buf, m_diag_arg,
+ m_byte_bound);
+ return ev.formatted_print ("out-of-bounds read at byte %s but region"
+ " ends at byte %E", start_buf,
+ m_byte_bound);
+ }
+ else
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds read from byte %s till"
+ " byte %s but %qE ends at byte %E",
+ start_buf, end_buf, m_diag_arg,
+ m_byte_bound);
+ return ev.formatted_print ("out-of-bounds read from byte %s till"
+ " byte %s but region ends at byte %E",
+ start_buf, end_buf, m_byte_bound);
+ }
+ }
+};
+
+/* Concrete subclass to complain about buffer underflows. */
+
+class buffer_underflow : public out_of_bounds
+{
+public:
+ buffer_underflow (const region *reg, tree diag_arg, byte_range range)
+ : out_of_bounds (reg, diag_arg, range)
+ {}
+
+ bool emit (rich_location *rich_loc) final override
+ {
+ diagnostic_metadata m;
+ m.add_cwe (124);
+ return warning_meta (rich_loc, m, get_controlling_option (),
+ "buffer underflow");
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev)
+ final override
+ {
+ byte_size_t start = m_out_of_bounds_range.get_start_byte_offset ();
+ byte_size_t end = m_out_of_bounds_range.get_last_byte_offset ();
+ char start_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (start, start_buf, SIGNED);
+ char end_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (end, end_buf, SIGNED);
+
+ if (start == end)
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds write at byte %s but %qE"
+ " starts at byte 0", start_buf,
+ m_diag_arg);
+ return ev.formatted_print ("out-of-bounds write at byte %s but region"
+ " starts at byte 0", start_buf);
+ }
+ else
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds write from byte %s till"
+ " byte %s but %qE starts at byte 0",
+ start_buf, end_buf, m_diag_arg);
+ return ev.formatted_print ("out-of-bounds write from byte %s till"
+ " byte %s but region starts at byte 0",
+ start_buf, end_buf);;
+ }
+ }
+};
+
+/* Concrete subclass to complain about buffer underreads. */
+
+class buffer_underread : public out_of_bounds
+{
+public:
+ buffer_underread (const region *reg, tree diag_arg, byte_range range)
+ : out_of_bounds (reg, diag_arg, range)
+ {}
+
+ bool emit (rich_location *rich_loc) final override
+ {
+ diagnostic_metadata m;
+ m.add_cwe (127);
+ return warning_meta (rich_loc, m, get_controlling_option (),
+ "buffer underread");
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev)
+ final override
+ {
+ byte_size_t start = m_out_of_bounds_range.get_start_byte_offset ();
+ byte_size_t end = m_out_of_bounds_range.get_last_byte_offset ();
+ char start_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (start, start_buf, SIGNED);
+ char end_buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ print_dec (end, end_buf, SIGNED);
+
+ if (start == end)
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds read at byte %s but %qE"
+ " starts at byte 0", start_buf,
+ m_diag_arg);
+ return ev.formatted_print ("out-of-bounds read at byte %s but region"
+ " starts at byte 0", start_buf);
+ }
+ else
+ {
+ if (m_diag_arg)
+ return ev.formatted_print ("out-of-bounds read from byte %s till"
+ " byte %s but %qE starts at byte 0",
+ start_buf, end_buf, m_diag_arg);
+ return ev.formatted_print ("out-of-bounds read from byte %s till"
+ " byte %s but region starts at byte 0",
+ start_buf, end_buf);;
+ }
+ }
+};
+
+/* May complain when the access on REG is out-of-bounds. */
+
+void region_model::check_region_bounds (const region *reg,
+ enum access_direction dir,
+ region_model_context *ctxt) const
+{
+ gcc_assert (ctxt);
+
+ region_offset reg_offset = reg->get_offset ();
+ const region *base_reg = reg_offset.get_base_region ();
+
+ /* Bail out on symbolic offsets or symbolic regions.
+ (e.g. because the analyzer did not see previous offsets on the latter,
+ it might think that a negative access is before the buffer). */
+ if (reg_offset.symbolic_p () || base_reg->symbolic_p ())
+ return;
+ byte_offset_t offset_unsigned
+ = reg_offset.get_bit_offset () >> LOG2_BITS_PER_UNIT;
+ /* The constant offset from a pointer is represented internally as a sizetype
+ but should be interpreted as a signed value here. The statement below
+ converts the offset to a signed integer with the same precision the
+ sizetype has on the target system.
+
+ For example, this is needed for out-of-bounds-3.c test1 to pass when
+ compiled with a 64-bit gcc build targeting 32-bit systems. */
+ byte_offset_t offset
+ = offset_unsigned.to_shwi (TYPE_PRECISION (size_type_node));
+
+ /* Find out how many bytes were accessed. */
+ const svalue *num_bytes_sval = reg->get_byte_size_sval (m_mgr);
+ tree num_bytes_tree = num_bytes_sval->maybe_get_constant ();
+ if (!num_bytes_tree || TREE_CODE (num_bytes_tree) != INTEGER_CST)
+ /* If we do not know how many bytes were read/written,
+ assume that at least one byte was read/written. */
+ num_bytes_tree = integer_one_node;
+
+ byte_range out (0, 0);
+ /* NUM_BYTES_TREE should always be interpreted as unsigned. */
+ byte_range read_bytes (offset, wi::to_offset (num_bytes_tree).to_uhwi ());
+ /* If read_bytes has a subset < 0, we do have an underflow. */
+ if (read_bytes.falls_short_of_p (0, &out))
+ {
+ tree diag_arg = get_representative_tree (reg->get_base_region ());
+ switch (dir)
+ {
+ default:
+ gcc_unreachable ();
+ break;
+ case DIR_READ:
+ ctxt->warn (new buffer_underread (reg, diag_arg, out));
+ break;
+ case DIR_WRITE:
+ ctxt->warn (new buffer_underflow (reg, diag_arg, out));
+ break;
+ }
+ }
+
+ const svalue *capacity = get_capacity (base_reg);
+ tree cst_capacity_tree = capacity->maybe_get_constant ();
+ if (!cst_capacity_tree || TREE_CODE (cst_capacity_tree) != INTEGER_CST)
+ return;
+
+ byte_range buffer (0, wi::to_offset (cst_capacity_tree));
+ /* If READ_BYTES exceeds BUFFER, we do have an overflow. */
+ if (read_bytes.exceeds_p (buffer, &out))
+ {
+ tree byte_bound = wide_int_to_tree (size_type_node,
+ buffer.get_next_byte_offset ());
+ tree diag_arg = get_representative_tree (reg->get_base_region ());
+
+ switch (dir)
+ {
+ default:
+ gcc_unreachable ();
+ break;
+ case DIR_READ:
+ ctxt->warn (new buffer_overread (reg, diag_arg, out, byte_bound));
+ break;
+ case DIR_WRITE:
+ ctxt->warn (new buffer_overflow (reg, diag_arg, out, byte_bound));
+ break;
+ }
+ }
+}
+
/* Ensure that all arguments at the call described by CD are checked
for poisoned values, by calling get_rvalue on each argument. */
@@ -1360,8 +1768,7 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
duplicates if any of the handling below also looks up the svalues,
but the deduplication code should deal with that. */
if (ctxt)
- for (unsigned arg_idx = 0; arg_idx < cd.num_args (); arg_idx++)
- cd.get_arg_svalue (arg_idx);
+ check_call_args (cd);
/* Some of the cases below update the lhs of the call based on the
return value, but not all. Provide a default value, which may
@@ -1481,7 +1888,6 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
/* These stdio builtins have external effects that are out
of scope for the analyzer: we only want to model the effects
on the return value. */
- check_call_args (cd);
break;
case BUILT_IN_VA_START:
@@ -2825,6 +3231,7 @@ region_model::check_region_access (const region *reg,
return;
check_region_for_taint (reg, dir, ctxt);
+ check_region_bounds (reg, dir, ctxt);
switch (dir)
{
@@ -3820,6 +4227,19 @@ region_model::get_representative_tree (const svalue *sval) const
return fixup_tree_for_diagnostic (expr);
}
+tree
+region_model::get_representative_tree (const region *reg) const
+{
+ svalue_set visited;
+ tree expr = get_representative_path_var (reg, &visited).m_tree;
+
+ /* Strip off any top-level cast. */
+ if (expr && TREE_CODE (expr) == NOP_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ return fixup_tree_for_diagnostic (expr);
+}
+
/* Implementation of region_model::get_representative_path_var.
Attempt to return a path_var that represents REG, or return
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index a9657e0..cdf1087 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -733,6 +733,7 @@ class region_model
region_model_context *ctxt);
tree get_representative_tree (const svalue *sval) const;
+ tree get_representative_tree (const region *reg) const;
path_var
get_representative_path_var (const svalue *sval,
svalue_set *visited) const;
@@ -868,6 +869,8 @@ class region_model
region_model_context *ctxt) const;
void check_region_size (const region *lhs_reg, const svalue *rhs_sval,
region_model_context *ctxt) const;
+ void check_region_bounds (const region *reg, enum access_direction dir,
+ region_model_context *ctxt) const;
void check_call_args (const call_details &cd) const;
void check_external_function_for_access_attr (const gcall *call,
diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index b78bf4e..f4aba6b 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -629,6 +629,14 @@ region::symbolic_for_unknown_ptr_p () const
return false;
}
+/* Return true if this is a symbolic region. */
+
+bool
+region::symbolic_p () const
+{
+ return get_kind () == RK_SYMBOLIC;
+}
+
/* Return true if this is a region for a decl with name DECL_NAME.
Intended for use when debugging (for assertions and conditional
breakpoints). */
@@ -1430,6 +1438,30 @@ offset_region::get_relative_concrete_offset (bit_offset_t *out) const
return false;
}
+/* Implementation of region::get_byte_size_sval vfunc for offset_region. */
+
+const svalue *
+offset_region::get_byte_size_sval (region_model_manager *mgr) const
+{
+ tree offset_cst = get_byte_offset ()->maybe_get_constant ();
+ byte_size_t byte_size;
+ /* If the offset points in the middle of the region,
+ return the remaining bytes. */
+ if (get_byte_size (&byte_size) && offset_cst)
+ {
+ byte_size_t offset = wi::to_offset (offset_cst);
+ byte_range r (0, byte_size);
+ if (r.contains_p (offset))
+ {
+ tree remaining_byte_size = wide_int_to_tree (size_type_node,
+ byte_size - offset);
+ return mgr->get_or_create_constant_svalue (remaining_byte_size);
+ }
+ }
+
+ return region::get_byte_size_sval (mgr);
+}
+
/* class sized_region : public region. */
/* Implementation of region::accept vfunc for sized_region. */
diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h
index a5b3029..20dffc7 100644
--- a/gcc/analyzer/region.h
+++ b/gcc/analyzer/region.h
@@ -211,6 +211,8 @@ public:
bool symbolic_for_unknown_ptr_p () const;
+ bool symbolic_p () const;
+
/* For most base regions it makes sense to track the bindings of the region
within the store. As an optimization, some are not tracked (to avoid
bloating the store object with redundant binding clusters). */
@@ -917,6 +919,8 @@ public:
const svalue *get_byte_offset () const { return m_byte_offset; }
bool get_relative_concrete_offset (bit_offset_t *out) const final override;
+ const svalue * get_byte_size_sval (region_model_manager *mgr) const;
+
private:
const svalue *m_byte_offset;
diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index 8bb76d7..505d598 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -971,19 +971,19 @@ fd_state_machine::check_for_dup (sm_context *sm_ctxt, const supernode *node,
state_t state_arg_1 = sm_ctxt->get_state (stmt, arg_1);
if (state_arg_1 == m_stop)
return;
- if (!(is_constant_fd_p (state_arg_1) || is_valid_fd_p (state_arg_1)))
+ if (!(is_constant_fd_p (state_arg_1) || is_valid_fd_p (state_arg_1)
+ || state_arg_1 == m_start))
{
check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl,
DIRS_READ_WRITE);
- if (kind == DUP_1)
- return;
+ return;
}
switch (kind)
{
case DUP_1:
if (lhs)
{
- if (is_constant_fd_p (state_arg_1))
+ if (is_constant_fd_p (state_arg_1) || state_arg_1 == m_start)
sm_ctxt->set_next_state (stmt, lhs, m_unchecked_read_write);
else
sm_ctxt->set_next_state (stmt, lhs,
@@ -999,7 +999,8 @@ fd_state_machine::check_for_dup (sm_context *sm_ctxt, const supernode *node,
if (state_arg_2 == m_stop)
return;
/* Check if -1 was passed as second argument to dup2. */
- if (!(is_constant_fd_p (state_arg_2) || is_valid_fd_p (state_arg_2)))
+ if (!(is_constant_fd_p (state_arg_2) || is_valid_fd_p (state_arg_2)
+ || state_arg_2 == m_start))
{
sm_ctxt->warn (
node, stmt, arg_2,
@@ -1011,7 +1012,7 @@ fd_state_machine::check_for_dup (sm_context *sm_ctxt, const supernode *node,
file descriptor i.e the first argument. */
if (lhs)
{
- if (is_constant_fd_p (state_arg_1))
+ if (is_constant_fd_p (state_arg_1) || state_arg_1 == m_start)
sm_ctxt->set_next_state (stmt, lhs, m_unchecked_read_write);
else
sm_ctxt->set_next_state (stmt, lhs,
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 46475f6..848c5e1 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -424,6 +424,73 @@ byte_range::contains_p (const byte_range &other, byte_range *out) const
return false;
}
+/* Return true if THIS and OTHER intersect and write the number
+ of bytes both buffers overlap to *OUT_NUM_OVERLAP_BYTES.
+
+ Otherwise return false. */
+
+bool
+byte_range::intersects_p (const byte_range &other,
+ byte_size_t *out_num_overlap_bytes) const
+{
+ if (get_start_byte_offset () < other.get_next_byte_offset ()
+ && other.get_start_byte_offset () < get_next_byte_offset ())
+ {
+ byte_offset_t overlap_start = MAX (get_start_byte_offset (),
+ other.get_start_byte_offset ());
+ byte_offset_t overlap_next = MIN (get_next_byte_offset (),
+ other.get_next_byte_offset ());
+ gcc_assert (overlap_next > overlap_start);
+ *out_num_overlap_bytes = overlap_next - overlap_start;
+ return true;
+ }
+ else
+ return false;
+}
+
+/* Return true if THIS exceeds OTHER and write the overhanging
+ byte range to OUT_OVERHANGING_BYTE_RANGE. */
+
+bool
+byte_range::exceeds_p (const byte_range &other,
+ byte_range *out_overhanging_byte_range) const
+{
+ if (other.get_last_byte_offset () < get_last_byte_offset ())
+ {
+ /* THIS definitely exceeds OTHER. */
+ byte_offset_t start = MAX (get_start_byte_offset (),
+ other.get_next_byte_offset ());
+ byte_offset_t size = get_next_byte_offset () - start;
+ gcc_assert (size > 0);
+ out_overhanging_byte_range->m_start_byte_offset = start;
+ out_overhanging_byte_range->m_size_in_bytes = size;
+ return true;
+ }
+ else
+ return false;
+}
+
+/* Return true if THIS falls short of OFFSET and write the
+ byte range fallen short to OUT_FALL_SHORT_BYTES. */
+
+bool
+byte_range::falls_short_of_p (byte_offset_t offset,
+ byte_range *out_fall_short_bytes) const
+{
+ if (get_start_byte_offset () < offset)
+ {
+ /* THIS falls short of OFFSET. */
+ byte_offset_t start = get_start_byte_offset ();
+ byte_offset_t size = MIN (offset, get_next_byte_offset ()) - start;
+ gcc_assert (size > 0);
+ out_fall_short_bytes->m_start_byte_offset = start;
+ out_fall_short_bytes->m_size_in_bytes = size;
+ return true;
+ }
+ else
+ return false;
+}
+
/* qsort comparator for byte ranges. */
int
diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 9b54c7b..ac8b685 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -310,6 +310,15 @@ struct byte_range
&& m_size_in_bytes == other.m_size_in_bytes);
}
+ bool intersects_p (const byte_range &other,
+ byte_size_t *out_num_overlap_bytes) const;
+
+ bool exceeds_p (const byte_range &other,
+ byte_range *out_overhanging_byte_range) const;
+
+ bool falls_short_of_p (byte_offset_t offset,
+ byte_range *out_fall_short_bytes) const;
+
byte_offset_t get_start_byte_offset () const
{
return m_start_byte_offset;
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 63277a5..fea41f4 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2022-08-11 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/102633
+ * c-gimplify.cc (c_gimplify_expr) <case DECL_EXPR>: Don't call
+ suppress_warning here.
+
2022-08-08 Tom Honermann <tom@honermann.net>
PR preprocessor/106426
diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
index a6f26c9..039a4b9 100644
--- a/gcc/c-family/c-gimplify.cc
+++ b/gcc/c-family/c-gimplify.cc
@@ -708,18 +708,6 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
break;
}
- case DECL_EXPR:
- /* This is handled mostly by gimplify.cc, but we have to deal with
- not warning about int x = x; as it is a GCC extension to turn off
- this warning but only if warn_init_self is zero. */
- if (VAR_P (DECL_EXPR_DECL (*expr_p))
- && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
- && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
- && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p))
- && !warn_init_self)
- suppress_warning (DECL_EXPR_DECL (*expr_p), OPT_Winit_self);
- break;
-
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index b5ecf92..985c96c 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,12 @@
+2022-08-11 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/102633
+ * c-parser.cc (c_parser_initializer): Add new tree parameter. Use it.
+ Call suppress_warning.
+ (c_parser_declaration_or_fndef): Pass d down to c_parser_initializer.
+ (c_parser_omp_declare_reduction): Pass omp_priv down to
+ c_parser_initializer.
+
2022-08-08 Tom Honermann <tom@honermann.net>
* c-parser.cc (c_parser_string_literal): Use char8_t as the type
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index fa93959..759f200 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1521,7 +1521,7 @@ static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
static tree c_parser_simple_asm_expr (c_parser *);
static tree c_parser_gnu_attributes (c_parser *);
-static struct c_expr c_parser_initializer (c_parser *);
+static struct c_expr c_parser_initializer (c_parser *, tree);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
struct obstack *);
static void c_parser_initelt (c_parser *, struct obstack *);
@@ -2286,7 +2286,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
int flag_sanitize_save = flag_sanitize;
if (TREE_CODE (d) == PARM_DECL)
flag_sanitize = 0;
- init = c_parser_initializer (parser);
+ init = c_parser_initializer (parser, d);
flag_sanitize = flag_sanitize_save;
finish_init ();
}
@@ -5211,11 +5211,13 @@ c_parser_type_name (c_parser *parser, bool alignas_ok)
Any expression without commas is accepted in the syntax for the
constant-expressions, with non-constant expressions rejected later.
+ DECL is the declaration we're parsing this initializer for.
+
This function is only used for top-level initializers; for nested
ones, see c_parser_initval. */
static struct c_expr
-c_parser_initializer (c_parser *parser)
+c_parser_initializer (c_parser *parser, tree decl)
{
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
return c_parser_braced_init (parser, NULL_TREE, false, NULL);
@@ -5224,6 +5226,15 @@ c_parser_initializer (c_parser *parser)
struct c_expr ret;
location_t loc = c_parser_peek_token (parser)->location;
ret = c_parser_expr_no_commas (parser, NULL);
+ /* This is handled mostly by gimplify.cc, but we have to deal with
+ not warning about int x = x; as it is a GCC extension to turn off
+ this warning but only if warn_init_self is zero. */
+ if (VAR_P (decl)
+ && !DECL_EXTERNAL (decl)
+ && !TREE_STATIC (decl)
+ && ret.value == decl
+ && !warn_init_self)
+ suppress_warning (decl, OPT_Winit_self);
if (TREE_CODE (ret.value) != STRING_CST
&& TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
ret = convert_lvalue_to_rvalue (loc, ret, true, true);
@@ -22588,7 +22599,7 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
location_t loc = c_parser_peek_token (parser)->location;
rich_location richloc (line_table, loc);
start_init (omp_priv, NULL_TREE, 0, &richloc);
- struct c_expr init = c_parser_initializer (parser);
+ struct c_expr init = c_parser_initializer (parser, omp_priv);
finish_init ();
finish_decl (omp_priv, loc, init.value,
init.original_type, NULL_TREE);
diff --git a/gcc/common/config/xtensa/xtensa-common.cc b/gcc/common/config/xtensa/xtensa-common.cc
index fbbe9b0..0f27763 100644
--- a/gcc/common/config/xtensa/xtensa-common.cc
+++ b/gcc/common/config/xtensa/xtensa-common.cc
@@ -34,6 +34,8 @@ static const struct default_options xtensa_option_optimization_table[] =
assembler, so GCC cannot do a good job of reordering blocks.
Do not enable reordering unless it is explicitly requested. */
{ OPT_LEVELS_ALL, OPT_freorder_blocks, NULL, 0 },
+ /* Split multi-word types early (pre-GCC10 behavior). */
+ { OPT_LEVELS_ALL, OPT_fsplit_wide_types_early, NULL, 1 },
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index bd60e65..e08bee1 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -8231,7 +8231,7 @@
[(match_operand:<VPRED> 1)
(const_int SVE_KNOWN_PTRUE)
(match_operand:SVE_FULL_F 2 "register_operand" "w")
- (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero" "wDz")]
+ (match_operand:SVE_FULL_F 3 "register_operand" "w")]
UNSPEC_COND_FCMUO))
(match_operand:<VPRED> 4 "register_operand" "Upa"))
(match_dup:<VPRED> 1)))
@@ -8267,7 +8267,7 @@
[(match_operand:<VPRED> 1)
(const_int SVE_KNOWN_PTRUE)
(match_operand:SVE_FULL_F 2 "register_operand" "w")
- (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero" "wDz")]
+ (match_operand:SVE_FULL_F 3 "register_operand" "w")]
UNSPEC_COND_FCMUO))
(not:<VPRED>
(match_operand:<VPRED> 4 "register_operand" "Upa")))
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index ef0aed2..3ea16db 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -347,9 +347,6 @@
; must not operate on inactive inputs if doing so could induce a fault.
(SVE_STRICT_GP 1)])
-;; If further include files are added the defintion of MD_INCLUDES
-;; must be updated.
-
(include "constraints.md")
(include "predicates.md")
(include "iterators.md")
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 7a2da1d..63a360b 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -69,6 +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 (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 fe7243c..6a04fb5 100644
--- a/gcc/config/i386/i386-builtins.cc
+++ b/gcc/config/i386/i386-builtins.cc
@@ -126,6 +126,9 @@ 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
the types lazily. */
@@ -1367,6 +1370,22 @@ 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 (!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);
+ }
+}
+
+static void
ix86_init_builtin_types (void)
{
tree float80_type_node, const_string_type_node;
@@ -1396,6 +1415,8 @@ ix86_init_builtin_types (void)
ix86_register_float16_builtin_type ();
+ ix86_register_bf16_builtin_type ();
+
const_string_type_node
= build_pointer_type (build_qualified_type
(char_type_node, TYPE_QUAL_CONST));
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index effc2f2..821d8c7 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -1209,6 +1209,8 @@ timode_scalar_chain::compute_convert_gain ()
rtx def_set = single_set (insn);
rtx src = SET_SRC (def_set);
rtx dst = SET_DEST (def_set);
+ HOST_WIDE_INT op1val;
+ int scost, vcost;
int igain = 0;
switch (GET_CODE (src))
@@ -1245,9 +1247,157 @@ timode_scalar_chain::compute_convert_gain ()
case ASHIFT:
case LSHIFTRT:
- /* For logical shifts by constant multiples of 8. */
- igain = optimize_insn_for_size_p () ? COSTS_N_BYTES (4)
- : COSTS_N_INSNS (1);
+ /* See ix86_expand_v1ti_shift. */
+ op1val = XINT (src, 1);
+ if (optimize_insn_for_size_p ())
+ {
+ if (op1val == 64 || op1val == 65)
+ scost = COSTS_N_BYTES (5);
+ else if (op1val >= 66)
+ scost = COSTS_N_BYTES (6);
+ else if (op1val == 1)
+ scost = COSTS_N_BYTES (8);
+ else
+ scost = COSTS_N_BYTES (9);
+
+ if ((op1val & 7) == 0)
+ vcost = COSTS_N_BYTES (5);
+ else if (op1val > 64)
+ vcost = COSTS_N_BYTES (10);
+ else
+ vcost = TARGET_AVX ? COSTS_N_BYTES (19) : COSTS_N_BYTES (23);
+ }
+ else
+ {
+ scost = COSTS_N_INSNS (2);
+ if ((op1val & 7) == 0)
+ vcost = COSTS_N_INSNS (1);
+ else if (op1val > 64)
+ vcost = COSTS_N_INSNS (2);
+ else
+ vcost = TARGET_AVX ? COSTS_N_INSNS (4) : COSTS_N_INSNS (5);
+ }
+ igain = scost - vcost;
+ break;
+
+ case ASHIFTRT:
+ /* See ix86_expand_v1ti_ashiftrt. */
+ op1val = XINT (src, 1);
+ if (optimize_insn_for_size_p ())
+ {
+ if (op1val == 64 || op1val == 127)
+ scost = COSTS_N_BYTES (7);
+ else if (op1val == 1)
+ scost = COSTS_N_BYTES (8);
+ else if (op1val == 65)
+ scost = COSTS_N_BYTES (10);
+ else if (op1val >= 66)
+ scost = COSTS_N_BYTES (11);
+ else
+ scost = COSTS_N_BYTES (9);
+
+ if (op1val == 127)
+ vcost = COSTS_N_BYTES (10);
+ else if (op1val == 64)
+ vcost = COSTS_N_BYTES (14);
+ else if (op1val == 96)
+ vcost = COSTS_N_BYTES (18);
+ else if (op1val >= 111)
+ vcost = COSTS_N_BYTES (15);
+ else if (TARGET_AVX2 && op1val == 32)
+ vcost = COSTS_N_BYTES (16);
+ else if (TARGET_SSE4_1 && op1val == 32)
+ vcost = COSTS_N_BYTES (20);
+ else if (op1val >= 96)
+ vcost = COSTS_N_BYTES (23);
+ else if ((op1val & 7) == 0)
+ vcost = COSTS_N_BYTES (28);
+ else if (TARGET_AVX2 && op1val < 32)
+ vcost = COSTS_N_BYTES (30);
+ else if (op1val == 1 || op1val >= 64)
+ vcost = COSTS_N_BYTES (42);
+ else
+ vcost = COSTS_N_BYTES (47);
+ }
+ else
+ {
+ if (op1val >= 65 && op1val <= 126)
+ scost = COSTS_N_INSNS (3);
+ else
+ scost = COSTS_N_INSNS (2);
+
+ if (op1val == 127)
+ vcost = COSTS_N_INSNS (2);
+ else if (op1val == 64)
+ vcost = COSTS_N_INSNS (3);
+ else if (op1val == 96)
+ vcost = COSTS_N_INSNS (4);
+ else if (op1val >= 111)
+ vcost = COSTS_N_INSNS (3);
+ else if (TARGET_AVX2 && op1val == 32)
+ vcost = COSTS_N_INSNS (3);
+ else if (TARGET_SSE4_1 && op1val == 32)
+ vcost = COSTS_N_INSNS (4);
+ else if (op1val >= 96)
+ vcost = COSTS_N_INSNS (5);
+ else if ((op1val & 7) == 0)
+ vcost = COSTS_N_INSNS (6);
+ else if (TARGET_AVX2 && op1val < 32)
+ vcost = COSTS_N_INSNS (6);
+ else if (op1val == 1 || op1val >= 64)
+ vcost = COSTS_N_INSNS (9);
+ else
+ vcost = COSTS_N_INSNS (10);
+ }
+ igain = scost - vcost;
+ break;
+
+ case ROTATE:
+ case ROTATERT:
+ /* See ix86_expand_v1ti_rotate. */
+ op1val = XINT (src, 1);
+ if (optimize_insn_for_size_p ())
+ {
+ scost = COSTS_N_BYTES (13);
+ if ((op1val & 31) == 0)
+ vcost = COSTS_N_BYTES (5);
+ else if ((op1val & 7) == 0)
+ vcost = TARGET_AVX ? COSTS_N_BYTES (13) : COSTS_N_BYTES (18);
+ else if (op1val > 32 && op1val < 96)
+ vcost = COSTS_N_BYTES (24);
+ else
+ vcost = COSTS_N_BYTES (19);
+ }
+ else
+ {
+ scost = COSTS_N_INSNS (3);
+ if ((op1val & 31) == 0)
+ vcost = COSTS_N_INSNS (1);
+ else if ((op1val & 7) == 0)
+ vcost = TARGET_AVX ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4);
+ else if (op1val > 32 && op1val < 96)
+ vcost = COSTS_N_INSNS (5);
+ else
+ vcost = COSTS_N_INSNS (1);
+ }
+ igain = scost - vcost;
+ break;
+
+ case COMPARE:
+ if (XEXP (src, 1) == const0_rtx)
+ {
+ if (GET_CODE (XEXP (src, 0)) == AND)
+ /* and;and;or (9 bytes) vs. ptest (5 bytes). */
+ igain = optimize_insn_for_size_p() ? COSTS_N_BYTES (4)
+ : COSTS_N_INSNS (2);
+ /* or (3 bytes) vs. ptest (5 bytes). */
+ else if (optimize_insn_for_size_p ())
+ igain = -COSTS_N_BYTES (2);
+ }
+ else if (XEXP (src, 1) == const1_rtx)
+ /* and;cmp -1 (7 bytes) vs. pcmpeqd;pxor;ptest (13 bytes). */
+ igain = optimize_insn_for_size_p() ? -COSTS_N_BYTES (6)
+ : -COSTS_N_INSNS (1);
break;
default:
@@ -1503,6 +1653,9 @@ timode_scalar_chain::convert_insn (rtx_insn *insn)
case ASHIFT:
case LSHIFTRT:
+ case ASHIFTRT:
+ case ROTATERT:
+ case ROTATE:
convert_op (&XEXP (src, 0), insn);
PUT_MODE (src, V1TImode);
break;
@@ -1861,11 +2014,13 @@ timode_scalar_to_vector_candidate_p (rtx_insn *insn)
case ASHIFT:
case LSHIFTRT:
- /* Handle logical shifts by integer constants between 0 and 120
- that are multiples of 8. */
+ case ASHIFTRT:
+ case ROTATERT:
+ case ROTATE:
+ /* Handle shifts/rotates by integer constants between 0 and 127. */
return REG_P (XEXP (src, 0))
&& CONST_INT_P (XEXP (src, 1))
- && (INTVAL (XEXP (src, 1)) & ~0x78) == 0;
+ && (INTVAL (XEXP (src, 1)) & ~0x7f) == 0;
default:
return false;
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index e2e1e18..b49daae 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see
FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_intel_96_format);
FLOAT_MODE (TF, 16, ieee_quad_format);
FLOAT_MODE (HF, 2, ieee_half_format);
+FLOAT_MODE (BF, 2, 0);
+ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format);
/* In ILP32 mode, XFmode has size 12 and alignment 4.
In LP64 mode, XFmode has size and alignment 16. */
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 5be76e1..fa3722a 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -2399,6 +2399,7 @@ classify_argument (machine_mode mode, const_tree type,
case E_CTImode:
return 0;
case E_HFmode:
+ case E_BFmode:
if (!(bit_offset % 64))
classes[0] = X86_64_SSEHF_CLASS;
else
@@ -2792,9 +2793,10 @@ construct_container (machine_mode mode, machine_mode orig_mode,
intreg++;
break;
case X86_64_SSEHF_CLASS:
+ tmpmode = (mode == BFmode ? BFmode : HFmode);
exp [nexps++]
= gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (HFmode,
+ gen_rtx_REG (tmpmode,
GET_SSE_REGNO (sse_regno)),
GEN_INT (i*8));
sse_regno++;
@@ -4001,8 +4003,8 @@ function_value_32 (machine_mode orig_mode, machine_mode mode,
/* Most things go in %eax. */
regno = AX_REG;
- /* Return _Float16/_Complex _Foat16 by sse register. */
- if (mode == HFmode)
+ /* Return __bf16/ _Float16/_Complex _Foat16 by sse register. */
+ if (mode == HFmode || mode == BFmode)
regno = FIRST_SSE_REG;
if (mode == HCmode)
{
@@ -4050,6 +4052,7 @@ function_value_64 (machine_mode orig_mode, machine_mode mode,
switch (mode)
{
+ case E_BFmode:
case E_HFmode:
case E_HCmode:
case E_SFmode:
@@ -5631,6 +5634,7 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands)
return "%vmovss\t{%1, %0|%0, %1}";
case MODE_HF:
+ case MODE_BF:
if (REG_P (operands[0]) && REG_P (operands[1]))
return "vmovsh\t{%d1, %0|%0, %d1}";
else
@@ -10648,6 +10652,11 @@ ix86_legitimate_constant_p (machine_mode mode, rtx x)
case CONST_VECTOR:
if (!standard_sse_constant_p (x, mode))
return false;
+ break;
+
+ case CONST_DOUBLE:
+ if (mode == E_BFmode)
+ return false;
default:
break;
@@ -19415,7 +19424,8 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
}
/* Require movement to gpr, and then store to memory. */
- if ((mode == HFmode || mode == HImode || mode == V2QImode)
+ if ((mode == HFmode || mode == HImode || mode == V2QImode
+ || mode == BFmode)
&& !TARGET_SSE4_1
&& SSE_CLASS_P (rclass)
&& !in_p && MEM_P (x))
@@ -22358,7 +22368,7 @@ ix86_scalar_mode_supported_p (scalar_mode mode)
return default_decimal_float_supported_p ();
else if (mode == TFmode)
return true;
- else if (mode == HFmode && TARGET_SSE2)
+ else if ((mode == HFmode || mode == BFmode) && TARGET_SSE2)
return true;
else
return default_scalar_mode_supported_p (mode);
@@ -22673,6 +22683,8 @@ ix86_mangle_type (const_tree type)
switch (TYPE_MODE (type))
{
+ case E_BFmode:
+ return "u6__bf16";
case E_HFmode:
/* _Float16 is "DF16_".
Align with clang's decision in https://reviews.llvm.org/D33719. */
@@ -22688,6 +22700,55 @@ 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
@@ -24745,6 +24806,15 @@ 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.h b/gcc/config/i386/i386.h
index f16df63..0da3dce 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1046,7 +1046,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \
|| (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \
|| (MODE) == V2DImode || (MODE) == V2QImode || (MODE) == DFmode \
- || (MODE) == HFmode)
+ || (MODE) == HFmode || (MODE) == BFmode)
#define VALID_SSE_REG_MODE(MODE) \
((MODE) == V1TImode || (MODE) == TImode \
@@ -1077,7 +1077,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|| (MODE) == CQImode || (MODE) == CHImode \
|| (MODE) == CSImode || (MODE) == CDImode \
|| (MODE) == SDmode || (MODE) == DDmode \
- || (MODE) == HFmode || (MODE) == HCmode \
+ || (MODE) == HFmode || (MODE) == HCmode || (MODE) == BFmode \
|| (MODE) == V2HImode || (MODE) == V2HFmode \
|| (MODE) == V1SImode || (MODE) == V4QImode || (MODE) == V2QImode \
|| (TARGET_64BIT \
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2fde8cd..5f7e245 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -499,7 +499,7 @@
;; Main data type used by the insn
(define_attr "mode"
- "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,SF,DF,XF,TF,V32HF,V16HF,V8HF,
+ "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,BF,SF,DF,XF,TF,V32HF,V16HF,V8HF,
V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF"
(const_string "unknown"))
@@ -1104,7 +1104,7 @@
;; GET_MODE_SIZE (<MODE>mode). For XFmode which depends on
;; command line options just use GET_MODE_SIZE macro.
(define_mode_attr MODE_SIZE [(QI "1") (HI "2") (SI "4") (DI "8")
- (TI "16") (HF "2") (SF "4") (DF "8")
+ (TI "16") (HF "2") (BF "2") (SF "4") (DF "8")
(XF "GET_MODE_SIZE (XFmode)")
(V16QI "16") (V32QI "32") (V64QI "64")
(V8HI "16") (V16HI "32") (V32HI "64")
@@ -1248,7 +1248,7 @@
(define_mode_iterator X87MODEF [SF DF XF])
;; All x87 floating point modes plus HFmode
-(define_mode_iterator X87MODEFH [HF SF DF XF])
+(define_mode_iterator X87MODEFH [HF SF DF XF BF])
;; All SSE floating point modes
(define_mode_iterator SSEMODEF [HF SF DF TF])
@@ -3439,9 +3439,11 @@
operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx);
})
-(define_insn "*pushhf_rex64"
- [(set (match_operand:HF 0 "push_operand" "=X,X")
- (match_operand:HF 1 "nonmemory_no_elim_operand" "r,x"))]
+(define_mode_iterator HFBF [HF BF])
+
+(define_insn "*push<mode>_rex64"
+ [(set (match_operand:HFBF 0 "push_operand" "=X,X")
+ (match_operand:HFBF 1 "nonmemory_no_elim_operand" "r,x"))]
"TARGET_64BIT"
{
/* Anything else should be already split before reg-stack. */
@@ -3452,9 +3454,9 @@
(set_attr "type" "push,multi")
(set_attr "mode" "DI,TI")])
-(define_insn "*pushhf"
- [(set (match_operand:HF 0 "push_operand" "=X,X")
- (match_operand:HF 1 "general_no_elim_operand" "rmF,x"))]
+(define_insn "*push<mode>"
+ [(set (match_operand:HFBF 0 "push_operand" "=X,X")
+ (match_operand:HFBF 1 "general_no_elim_operand" "rmF,x"))]
"!TARGET_64BIT"
{
/* Anything else should be already split before reg-stack. */
@@ -3493,7 +3495,7 @@
(set_attr "unit" "i387,*,*")
(set_attr "mode" "SF,SI,SF")])
-(define_mode_iterator MODESH [SF HF])
+(define_mode_iterator MODESH [SF HF BF])
;; %%% Kill this when call knows how to work this out.
(define_split
[(set (match_operand:MODESH 0 "push_operand")
@@ -3981,18 +3983,21 @@
]
(const_string "*")))])
-(define_insn "*movhf_internal"
- [(set (match_operand:HF 0 "nonimmediate_operand"
+(define_mode_attr hfbfconstf
+ [(HF "F") (BF "")])
+
+(define_insn "*mov<mode>_internal"
+ [(set (match_operand:HFBF 0 "nonimmediate_operand"
"=?r,?r,?r,?m,v,v,?r,m,?v,v")
- (match_operand:HF 1 "general_operand"
- "r ,F ,m ,rF,C,v, v,v,r ,m"))]
+ (match_operand:HFBF 1 "general_operand"
+ "r ,F ,m ,r<hfbfconstf>,C,v, v,v,r ,m"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (lra_in_progress
|| reload_completed
|| !CONST_DOUBLE_P (operands[1])
|| (TARGET_SSE2
- && standard_sse_constant_p (operands[1], HFmode) == 1)
- || memory_operand (operands[0], HFmode))"
+ && standard_sse_constant_p (operands[1], <MODE>mode) == 1)
+ || memory_operand (operands[0], <MODE>mode))"
{
switch (get_attr_type (insn))
{
@@ -4087,7 +4092,13 @@
(not (match_test "TARGET_HIMODE_MATH"))))
(const_string "SI")
]
- (const_string "HI")))])
+ (const_string "HI")))
+ (set (attr "enabled")
+ (cond [(and (match_test "<MODE>mode == BFmode")
+ (eq_attr "alternative" "1"))
+ (symbol_ref "false")
+ ]
+ (const_string "*")))])
(define_split
[(set (match_operand 0 "any_fp_register_operand")
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 064596d..4f16bb7 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -931,6 +931,14 @@
return val <= 255*8 && val % 8 == 0;
})
+;; Match 1 to 255 except multiples of 8
+(define_predicate "const_0_to_255_not_mul_8_operand"
+ (match_code "const_int")
+{
+ unsigned HOST_WIDE_INT val = INTVAL (op);
+ return val <= 255 && val % 8 != 0;
+})
+
;; Return true if OP is CONST_INT >= 1 and <= 31 (a valid operand
;; for shift & compare patterns, as shifting by 0 does not change flags).
(define_predicate "const_1_to_31_operand"
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index ccd9d00..b23f07e 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -15995,10 +15995,28 @@
(define_expand "ashlv1ti3"
[(set (match_operand:V1TI 0 "register_operand")
+ (ashift:V1TI
+ (match_operand:V1TI 1 "register_operand")
+ (match_operand:QI 2 "general_operand")))]
+ "TARGET_SSE2 && TARGET_64BIT"
+{
+ if (!CONST_INT_P (operands[2]))
+ {
+ ix86_expand_v1ti_shift (ASHIFT, operands);
+ DONE;
+ }
+})
+
+(define_insn_and_split "*ashlv1ti3_internal"
+ [(set (match_operand:V1TI 0 "register_operand")
(ashift:V1TI
(match_operand:V1TI 1 "register_operand")
- (match_operand:QI 2 "general_operand")))]
- "TARGET_SSE2 && TARGET_64BIT"
+ (match_operand:SI 2 "const_0_to_255_not_mul_8_operand")))]
+ "TARGET_SSE2 && TARGET_64BIT
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
{
ix86_expand_v1ti_shift (ASHIFT, operands);
DONE;
@@ -16011,6 +16029,24 @@
(match_operand:QI 2 "general_operand")))]
"TARGET_SSE2 && TARGET_64BIT"
{
+ if (!CONST_INT_P (operands[2]))
+ {
+ ix86_expand_v1ti_shift (LSHIFTRT, operands);
+ DONE;
+ }
+})
+
+(define_insn_and_split "*lshrv1ti3_internal"
+ [(set (match_operand:V1TI 0 "register_operand")
+ (lshiftrt:V1TI
+ (match_operand:V1TI 1 "register_operand")
+ (match_operand:SI 2 "const_0_to_255_not_mul_8_operand")))]
+ "TARGET_SSE2 && TARGET_64BIT
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
ix86_expand_v1ti_shift (LSHIFTRT, operands);
DONE;
})
@@ -16022,6 +16058,25 @@
(match_operand:QI 2 "general_operand")))]
"TARGET_SSE2 && TARGET_64BIT"
{
+ if (!CONST_INT_P (operands[2]))
+ {
+ ix86_expand_v1ti_ashiftrt (operands);
+ DONE;
+ }
+})
+
+
+(define_insn_and_split "*ashrv1ti3_internal"
+ [(set (match_operand:V1TI 0 "register_operand")
+ (ashiftrt:V1TI
+ (match_operand:V1TI 1 "register_operand")
+ (match_operand:SI 2 "const_0_to_255_operand")))]
+ "TARGET_SSE2 && TARGET_64BIT
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
ix86_expand_v1ti_ashiftrt (operands);
DONE;
})
@@ -16033,6 +16088,24 @@
(match_operand:QI 2 "general_operand")))]
"TARGET_SSE2 && TARGET_64BIT"
{
+ if (!CONST_INT_P (operands[2]))
+ {
+ ix86_expand_v1ti_rotate (ROTATE, operands);
+ DONE;
+ }
+})
+
+(define_insn_and_split "*rotlv1ti3_internal"
+ [(set (match_operand:V1TI 0 "register_operand")
+ (rotate:V1TI
+ (match_operand:V1TI 1 "register_operand")
+ (match_operand:SI 2 "const_0_to_255_operand")))]
+ "TARGET_SSE2 && TARGET_64BIT
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
ix86_expand_v1ti_rotate (ROTATE, operands);
DONE;
})
@@ -16044,6 +16117,24 @@
(match_operand:QI 2 "general_operand")))]
"TARGET_SSE2 && TARGET_64BIT"
{
+ if (!CONST_INT_P (operands[2]))
+ {
+ ix86_expand_v1ti_rotate (ROTATERT, operands);
+ DONE;
+ }
+})
+
+(define_insn_and_split "*rotrv1ti3_internal"
+ [(set (match_operand:V1TI 0 "register_operand")
+ (rotatert:V1TI
+ (match_operand:V1TI 1 "register_operand")
+ (match_operand:SI 2 "const_0_to_255_operand")))]
+ "TARGET_SSE2 && TARGET_64BIT
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
ix86_expand_v1ti_rotate (ROTATERT, operands);
DONE;
})
diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index a183b6a..032f426 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -268,10 +268,25 @@
(define_expand "movoo"
[(set (match_operand:OO 0 "nonimmediate_operand")
(match_operand:OO 1 "input_operand"))]
- "TARGET_MMA"
+ ""
{
- rs6000_emit_move (operands[0], operands[1], OOmode);
- DONE;
+ if (TARGET_MMA)
+ {
+ rs6000_emit_move (operands[0], operands[1], OOmode);
+ DONE;
+ }
+ else if (currently_expanding_to_rtl && seen_error ())
+ {
+ /* PR103353 shows we may want to continue to expand the __builtin_vsx_lxvp
+ built-in function, even if we have already emitted error messages about
+ some missing required conditions. As shown in that PR, without one
+ explicit mov optab on OOmode provided, it would call emit_move_insn
+ recursively. So we allow this pattern to be generated when we are
+ expanding to RTL and have seen errors. It would not cause further ICEs
+ as the compilation would stop soon after expanding. */
+ }
+ else
+ gcc_unreachable ();
})
(define_insn_and_split "*movoo"
@@ -300,10 +315,22 @@
(define_expand "movxo"
[(set (match_operand:XO 0 "nonimmediate_operand")
(match_operand:XO 1 "input_operand"))]
- "TARGET_MMA"
+ ""
{
- rs6000_emit_move (operands[0], operands[1], XOmode);
- DONE;
+ if (TARGET_MMA)
+ {
+ rs6000_emit_move (operands[0], operands[1], XOmode);
+ DONE;
+ }
+ else if (currently_expanding_to_rtl && seen_error ())
+ {
+ /* PR103353 shows we may want to continue to expand the __builtin_vsx_lxvp
+ built-in function, even if we have already emitted error messages about
+ some missing required conditions. So do the same handlings for XOmode
+ as OOmode here. */
+ }
+ else
+ gcc_unreachable ();
})
(define_insn_and_split "*movxo"
diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc
index 2819773..12afa86 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -830,44 +830,8 @@ rs6000_init_builtins (void)
fprintf (stderr, "\nAutogenerated built-in functions:\n\n");
for (int i = 1; i < (int) RS6000_BIF_MAX; i++)
{
- bif_enable e = rs6000_builtin_info[i].enable;
- if (e == ENB_P5 && !TARGET_POPCNTB)
- continue;
- if (e == ENB_P6 && !TARGET_CMPB)
- continue;
- if (e == ENB_P6_64 && !(TARGET_CMPB && TARGET_POWERPC64))
- continue;
- if (e == ENB_ALTIVEC && !TARGET_ALTIVEC)
- continue;
- if (e == ENB_VSX && !TARGET_VSX)
- continue;
- if (e == ENB_P7 && !TARGET_POPCNTD)
- continue;
- if (e == ENB_P7_64 && !(TARGET_POPCNTD && TARGET_POWERPC64))
- continue;
- if (e == ENB_P8 && !TARGET_DIRECT_MOVE)
- continue;
- if (e == ENB_P8V && !TARGET_P8_VECTOR)
- continue;
- if (e == ENB_P9 && !TARGET_MODULO)
- continue;
- if (e == ENB_P9_64 && !(TARGET_MODULO && TARGET_POWERPC64))
- continue;
- if (e == ENB_P9V && !TARGET_P9_VECTOR)
- continue;
- if (e == ENB_IEEE128_HW && !TARGET_FLOAT128_HW)
- continue;
- if (e == ENB_DFP && !TARGET_DFP)
- continue;
- if (e == ENB_CRYPTO && !TARGET_CRYPTO)
- continue;
- if (e == ENB_HTM && !TARGET_HTM)
- continue;
- if (e == ENB_P10 && !TARGET_POWER10)
- continue;
- if (e == ENB_P10_64 && !(TARGET_POWER10 && TARGET_POWERPC64))
- continue;
- if (e == ENB_MMA && !TARGET_MMA)
+ enum rs6000_gen_builtins fn_code = (enum rs6000_gen_builtins) i;
+ if (!rs6000_builtin_is_supported (fn_code))
continue;
tree fntype = rs6000_builtin_info[i].fntype;
tree t = TREE_TYPE (fntype);
@@ -3370,29 +3334,8 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */,
but check for actual availability now, during expand time. For
invalid builtins, generate a normal call. */
bifdata *bifaddr = &rs6000_builtin_info[uns_fcode];
- bif_enable e = bifaddr->enable;
-
- if (!(e == ENB_ALWAYS
- || (e == ENB_P5 && TARGET_POPCNTB)
- || (e == ENB_P6 && TARGET_CMPB)
- || (e == ENB_P6_64 && TARGET_CMPB && TARGET_POWERPC64)
- || (e == ENB_ALTIVEC && TARGET_ALTIVEC)
- || (e == ENB_CELL && TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL)
- || (e == ENB_VSX && TARGET_VSX)
- || (e == ENB_P7 && TARGET_POPCNTD)
- || (e == ENB_P7_64 && TARGET_POPCNTD && TARGET_POWERPC64)
- || (e == ENB_P8 && TARGET_DIRECT_MOVE)
- || (e == ENB_P8V && TARGET_P8_VECTOR)
- || (e == ENB_P9 && TARGET_MODULO)
- || (e == ENB_P9_64 && TARGET_MODULO && TARGET_POWERPC64)
- || (e == ENB_P9V && TARGET_P9_VECTOR)
- || (e == ENB_IEEE128_HW && TARGET_FLOAT128_HW)
- || (e == ENB_DFP && TARGET_DFP)
- || (e == ENB_CRYPTO && TARGET_CRYPTO)
- || (e == ENB_HTM && TARGET_HTM)
- || (e == ENB_P10 && TARGET_POWER10)
- || (e == ENB_P10_64 && TARGET_POWER10 && TARGET_POWERPC64)
- || (e == ENB_MMA && TARGET_MMA)))
+
+ if (!rs6000_builtin_is_supported (fcode))
{
rs6000_invalid_builtin (fcode);
return expand_call (exp, target, ignore);
diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h
index 8ee8c98..b9e82c0 100644
--- a/gcc/config/rs6000/rs6000-internal.h
+++ b/gcc/config/rs6000/rs6000-internal.h
@@ -82,7 +82,6 @@ extern const char *rs6000_machine;
from rs6000-logue.cc */
extern int uses_TOC (void);
-extern bool rs6000_global_entry_point_needed_p (void);
extern void rs6000_output_function_prologue (FILE *file);
extern void rs6000_output_function_epilogue (FILE *file);
extern bool rs6000_function_ok_for_sibcall (tree decl, tree exp);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ed83b97..f1c96b4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2022-08-15 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106276
+ * typeck.cc (can_do_rvo_p): New.
+ (maybe_warn_pessimizing_move): Warn when moving a temporary object
+ in a return statement prevents copy elision.
+
+2022-08-11 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/102633
+ * decl.cc (cp_finish_decl): Call suppress_warning.
+
2022-08-07 Jakub Jelinek <jakub@redhat.com>
PR c++/88174
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 70ad681..ff56fdd 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8253,6 +8253,14 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
&& !TYPE_REF_P (type))
TREE_CONSTANT (decl) = 1;
}
+ /* This is handled mostly by gimplify.cc, but we have to deal with
+ not warning about int x = x; as it is a GCC extension to turn off
+ this warning but only if warn_init_self is zero. */
+ if (!DECL_EXTERNAL (decl)
+ && !TREE_STATIC (decl)
+ && decl == tree_strip_any_location_wrapper (init)
+ && !warn_init_self)
+ suppress_warning (decl, OPT_Winit_self);
}
if (flag_openmp
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 6e4f23a..15548e5 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10287,12 +10287,29 @@ can_do_nrvo_p (tree retval, tree functype)
/* The cv-unqualified type of the returned value must be the
same as the cv-unqualified return type of the
function. */
- && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
- (TYPE_MAIN_VARIANT (functype)))
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (retval)),
+ TYPE_MAIN_VARIANT (functype))
/* And the returned value must be non-volatile. */
&& !TYPE_VOLATILE (TREE_TYPE (retval)));
}
+/* Like can_do_nrvo_p, but we check if we're trying to move a class
+ prvalue. */
+
+static bool
+can_do_rvo_p (tree retval, tree functype)
+{
+ if (functype == error_mark_node)
+ return false;
+ if (retval)
+ STRIP_ANY_LOCATION_WRAPPER (retval);
+ return (retval != NULL_TREE
+ && !glvalue_p (retval)
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (retval)),
+ TYPE_MAIN_VARIANT (functype))
+ && !TYPE_VOLATILE (TREE_TYPE (retval)));
+}
+
/* If we should treat RETVAL, an expression being returned, as if it were
designated by an rvalue, returns it adjusted accordingly; otherwise, returns
NULL_TREE. See [class.copy.elision]. RETURN_P is true if this is a return
@@ -10401,12 +10418,20 @@ maybe_warn_pessimizing_move (tree retval, tree functype)
"prevents copy elision"))
inform (loc, "remove %<std::move%> call");
}
+ else if (can_do_rvo_p (arg, functype))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wpessimizing_move,
+ "moving a temporary object in a return statement "
+ "prevents copy elision"))
+ inform (loc, "remove %<std::move%> call");
+ }
/* Warn if the move is redundant. It is redundant when we would
do maybe-rvalue overload resolution even without std::move. */
else if (warn_redundant_move
&& (moved = treat_lvalue_as_rvalue_p (arg, /*return*/true)))
{
- /* Make sure that the overload resolution would actually succeed
+ /* Make sure that overload resolution would actually succeed
if we removed the std::move call. */
tree t = convert_for_initialization (NULL_TREE, functype,
moved,
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 0af724b..0d4c037 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,37 @@
+2022-08-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-tree.h (d_defer_declaration): Declare.
+ * decl.cc (function_needs_inline_definition_p): Defer checking
+ DECL_UNINLINABLE and DECL_DECLARED_INLINE_P.
+ (maybe_build_decl_tree): Call d_defer_declaration instead of
+ build_decl_tree.
+ * modules.cc (deferred_inline_declarations): New variable.
+ (build_module_tree): Set deferred_inline_declarations and a handle
+ declarations pushed to it.
+ (d_defer_declaration): New function.
+
+2022-08-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/106623
+ * d-codegen.cc (underlying_complex_expr): New function.
+ (d_build_call): Handle passing native complex objects as the
+ library-defined equivalent.
+ * d-tree.h (underlying_complex_expr): Declare.
+ * expr.cc (ExprVisitor::visit (DotVarExp *)): Call
+ underlying_complex_expr instead of build_vconvert.
+
+2022-08-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-compiler.cc (Compiler::onParseModule): Call create_tinfo_types
+ when module name is object.
+ * typeinfo.cc (create_tinfo_types): Add guard for multiple
+ invocations.
+
+2022-08-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * d-codegen.cc (build_delegate_cst): Give anonymous delegate field
+ names same as per ABI spec.
+
2022-08-09 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/106563
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 3fd4bee..aa6bc9e 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -419,8 +419,8 @@ build_delegate_cst (tree method, tree object, Type *type)
{
/* Convert a function method into an anonymous delegate. */
ctype = make_struct_type ("delegate()", 2,
- get_identifier ("object"), TREE_TYPE (object),
- get_identifier ("func"), TREE_TYPE (method));
+ get_identifier ("ptr"), TREE_TYPE (object),
+ get_identifier ("funcptr"), TREE_TYPE (method));
TYPE_DELEGATE (ctype) = 1;
}
@@ -1588,6 +1588,32 @@ complex_expr (tree type, tree re, tree im)
type, re, im);
}
+/* Build a two-field record TYPE representing the complex expression EXPR. */
+
+tree
+underlying_complex_expr (tree type, tree expr)
+{
+ gcc_assert (list_length (TYPE_FIELDS (type)) == 2);
+
+ expr = d_save_expr (expr);
+
+ /* Build a constructor from the real and imaginary parts. */
+ if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (expr)) &&
+ (!INDIRECT_REF_P (expr)
+ || !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (expr, 0)))))
+ {
+ vec <constructor_elt, va_gc> *ve = NULL;
+ CONSTRUCTOR_APPEND_ELT (ve, TYPE_FIELDS (type),
+ real_part (expr));
+ CONSTRUCTOR_APPEND_ELT (ve, TREE_CHAIN (TYPE_FIELDS (type)),
+ imaginary_part (expr));
+ return build_constructor (type, ve);
+ }
+
+ /* Replace type in the reinterpret cast with a cast to the record type. */
+ return build_vconvert (type, expr);
+}
+
/* Cast EXP (which should be a pointer) to TYPE* and then indirect.
The back-end requires this cast in many cases. */
@@ -2214,6 +2240,14 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
build_address (targ));
}
+ /* Complex types are exposed as special types with an underlying
+ struct representation, if we are passing the native type to a
+ function that accepts the library-defined version, then ensure
+ it is properly reinterpreted as the underlying struct type. */
+ if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (targ))
+ && arg->type->isTypeStruct ())
+ targ = underlying_complex_expr (build_ctype (arg->type), targ);
+
/* Type `noreturn` is a terminator, as no other arguments can possibly
be evaluated after it. */
if (TREE_TYPE (targ) == noreturn_type_node)
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index ada9721..ef19df1 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -130,8 +130,7 @@ Compiler::onParseModule (Module *m)
{
if (md->packages.length == 0)
{
- Identifier *id = (md && md->id) ? md->id : m->ident;
- if (!strcmp (id->toChars (), "object"))
+ if (!strcmp (md->id->toChars (), "object"))
{
create_tinfo_types (m);
return;
@@ -147,6 +146,14 @@ Compiler::onParseModule (Module *m)
}
}
}
+ else if (m->ident)
+ {
+ if (!strcmp (m->ident->toChars (), "object"))
+ {
+ create_tinfo_types (m);
+ return;
+ }
+ }
if (!flag_no_builtin)
d_add_builtin_module (m);
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index c3e95e4..4885cfe 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -576,6 +576,7 @@ extern tree size_mult_expr (tree, tree);
extern tree real_part (tree);
extern tree imaginary_part (tree);
extern tree complex_expr (tree, tree, tree);
+extern tree underlying_complex_expr (tree, tree);
extern tree indirect_ref (tree, tree);
extern tree build_deref (tree);
extern tree build_pointer_index (tree, tree);
@@ -672,6 +673,7 @@ extern tree maybe_expand_intrinsic (tree);
extern void build_module_tree (Module *);
extern tree d_module_context (void);
extern void register_module_decl (Declaration *);
+extern void d_defer_declaration (Declaration *);
extern void d_finish_compilation (tree *, int);
/* In runtime.cc. */
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 0131b01..e91aee3 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1046,18 +1046,10 @@ function_needs_inline_definition_p (FuncDeclaration *fd)
if (!DECL_EXTERNAL (fd->csym))
return false;
- /* Non-inlineable functions are always external. */
- if (DECL_UNINLINABLE (fd->csym))
- return false;
-
/* No function body available for inlining. */
if (!fd->fbody)
return false;
- /* Ignore functions that aren't decorated with `pragma(inline)'. */
- if (fd->inlining != PINLINE::always)
- return false;
-
/* These functions are tied to the module they are defined in. */
if (fd->isFuncLiteralDeclaration ()
|| fd->isUnitTestDeclaration ()
@@ -1070,6 +1062,14 @@ function_needs_inline_definition_p (FuncDeclaration *fd)
if (function_defined_in_root_p (fd))
return false;
+ /* Non-inlineable functions are always external. */
+ if (DECL_UNINLINABLE (fd->csym))
+ return false;
+
+ /* Ignore functions that aren't decorated with `pragma(inline)'. */
+ if (!DECL_DECLARED_INLINE_P (fd->csym))
+ return false;
+
/* Weak functions cannot be inlined. */
if (lookup_attribute ("weak", DECL_ATTRIBUTES (fd->csym)))
return false;
@@ -1081,8 +1081,8 @@ function_needs_inline_definition_p (FuncDeclaration *fd)
return true;
}
-/* If the variable or function declaration in DECL needs to be defined, call
- build_decl_tree on it now before returning its back-end symbol. */
+/* If the variable or function declaration in DECL needs to be defined, add it
+ to the list of deferred declarations to build later. */
static tree
maybe_build_decl_tree (Declaration *decl)
@@ -1103,7 +1103,7 @@ maybe_build_decl_tree (Declaration *decl)
if (function_needs_inline_definition_p (fd))
{
DECL_EXTERNAL (fd->csym) = 0;
- build_decl_tree (fd);
+ d_defer_declaration (fd);
}
}
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 40c2689..140df7e 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1892,7 +1892,7 @@ public:
underlying is really a complex type. */
if (e->e1->type->ty == TY::Tenum
&& e->e1->type->isTypeEnum ()->sym->isSpecial ())
- object = build_vconvert (build_ctype (tb), object);
+ object = underlying_complex_expr (build_ctype (tb), object);
this->result_ = component_ref (object, get_symbol_decl (vd));
}
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index edc7912..0aac8fe 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -121,6 +121,9 @@ static module_info *current_testing_module;
static Module *current_module_decl;
+/* Any inline symbols that were deferred during codegen. */
+vec<Declaration *> *deferred_inline_declarations;
+
/* Returns an internal function identified by IDENT. This is used
by both module initialization and dso handlers. */
@@ -724,6 +727,9 @@ build_module_tree (Module *decl)
current_testing_module = &mitest;
current_module_decl = decl;
+ vec<Declaration *> deferred_decls = vNULL;
+ deferred_inline_declarations = &deferred_decls;
+
/* Layout module members. */
if (decl->members)
{
@@ -811,9 +817,14 @@ build_module_tree (Module *decl)
layout_moduleinfo (decl);
}
+ /* Process all deferred functions after finishing module. */
+ for (size_t i = 0; i < deferred_decls.length (); ++i)
+ build_decl_tree (deferred_decls[i]);
+
current_moduleinfo = NULL;
current_testing_module = NULL;
current_module_decl = NULL;
+ deferred_inline_declarations = NULL;
}
/* Returns the current function or module context for the purpose
@@ -888,6 +899,15 @@ register_module_decl (Declaration *d)
}
}
+/* Add DECL as a declaration to emit at the end of the current module. */
+
+void
+d_defer_declaration (Declaration *decl)
+{
+ gcc_assert (deferred_inline_declarations != NULL);
+ deferred_inline_declarations->safe_push (decl);
+}
+
/* Wrapup all global declarations and start the final compilation. */
void
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index d1f0d59..3577f66 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -244,6 +244,10 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
void
create_tinfo_types (Module *mod)
{
+ /* Already generated internal types for the object module. */
+ if (object_module != NULL)
+ return;
+
/* Build the internal TypeInfo and ClassInfo types.
See TypeInfoVisitor for documentation of field layout. */
make_internal_typeinfo (TK_TYPEINFO_TYPE, Identifier::idPool ("TypeInfo"),
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8a0d1f2..685d74c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -421,6 +421,7 @@ Objective-C and Objective-C++ Dialects}.
-Wno-analyzer-mismatching-deallocation @gol
-Wno-analyzer-null-argument @gol
-Wno-analyzer-null-dereference @gol
+-Wno-analyzer-out-of-bounds @gol
-Wno-analyzer-possible-null-argument @gol
-Wno-analyzer-possible-null-dereference @gol
-Wno-analyzer-putenv-of-auto-var @gol
@@ -9725,6 +9726,7 @@ Enabling this option effectively enables the following warnings:
-Wanalyzer-mismatching-deallocation @gol
-Wanalyzer-null-argument @gol
-Wanalyzer-null-dereference @gol
+-Wanalyzer-out-of-bounds @gol
-Wanalyzer-possible-null-argument @gol
-Wanalyzer-possible-null-dereference @gol
-Wanalyzer-putenv-of-auto-var @gol
@@ -9946,6 +9948,19 @@ pairs using attribute @code{malloc}.
See @uref{https://cwe.mitre.org/data/definitions/762.html, CWE-762: Mismatched Memory Management Routines}.
+@item -Wno-analyzer-out-of-bounds
+@opindex Wanalyzer-out-of-bounds
+@opindex Wno-analyzer-out-of-bounds
+This warning requires @option{-fanalyzer} to enable it; use
+@option{-Wno-analyzer-out-of-bounds} to disable it.
+
+This diagnostic warns for path through the code in which a buffer is
+definitely read or written out-of-bounds. The diagnostic only applies
+for cases where the analyzer is able to determine a constant offset and
+for accesses past the end of a buffer, also a constant capacity.
+
+See @uref{https://cwe.mitre.org/data/definitions/119.html, CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer}.
+
@item -Wno-analyzer-possible-null-argument
@opindex Wanalyzer-possible-null-argument
@opindex Wno-analyzer-possible-null-argument
@@ -14800,9 +14815,9 @@ duplicated when threading jumps.
@item max-jump-thread-paths
The maximum number of paths to consider when searching for jump threading
-opportunities. When arriving at a block incoming edges are only considered
-if the number of paths to be searched sofar multiplied by the incoming
-edge degree does not exhaust the specified maximum number of paths to
+opportunities. When arriving at a block, incoming edges are only considered
+if the number of paths to be searched so far multiplied by the number of
+incoming edges does not exhaust the specified maximum number of paths to
consider.
@item max-fields-for-field-sensitive
@@ -21582,14 +21597,25 @@ The following extension options are common to the listed CPUs:
@table @samp
@item +nodsp
-Disable the DSP instructions on @samp{cortex-m33}, @samp{cortex-m35p}.
+Disable the DSP instructions on @samp{cortex-m33}, @samp{cortex-m35p}
+and @samp{cortex-m55}. Also disable the M-Profile Vector Extension (MVE)
+integer and single precision floating-point instructions on @samp{cortex-m55}.
+
+@item +nomve
+Disable the M-Profile Vector Extension (MVE) integer and single precision
+floating-point instructions on @samp{cortex-m55}.
+
+@item +nomve.fp
+Disable the M-Profile Vector Extension (MVE) single precision floating-point
+instructions on @samp{cortex-m55}.
@item +nofp
Disables the floating-point instructions on @samp{arm9e},
@samp{arm946e-s}, @samp{arm966e-s}, @samp{arm968e-s}, @samp{arm10e},
@samp{arm1020e}, @samp{arm1022e}, @samp{arm926ej-s},
@samp{arm1026ej-s}, @samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8},
-@samp{cortex-m4}, @samp{cortex-m7}, @samp{cortex-m33} and @samp{cortex-m35p}.
+@samp{cortex-m4}, @samp{cortex-m7}, @samp{cortex-m33}, @samp{cortex-m35p}
+and @samp{cortex-m55}.
Disables the floating-point and SIMD instructions on
@samp{generic-armv7-a}, @samp{cortex-a5}, @samp{cortex-a7},
@samp{cortex-a8}, @samp{cortex-a9}, @samp{cortex-a12},
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index d34e0b5..59d673b 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -246,7 +246,7 @@ including OpenMP and OpenACC support for parallel programming.
The GNU Fortran compiler passes the
@uref{http://www.fortran-2000.com/ArnaudRecipes/fcvs21_f95.html,
NIST Fortran 77 Test Suite}, and produces acceptable results on the
-@uref{https://www.netlib.org/lapack/faq.html#1.21, LAPACK Test Suite}.
+@uref{https://www.netlib.org/lapack/faq.html, LAPACK Test Suite}.
It also provides respectable performance on
the @uref{https://polyhedron.com/?page_id=175,
Polyhedron Fortran compiler benchmarks} and the
@@ -441,7 +441,7 @@ found in the following sections of the documentation.
Additionally, the GNU Fortran compilers supports the OpenMP specification
(version 4.5 and partial support of the features of the 5.0 version,
-@url{https://openmp.org/@/openmp-specifications/}).
+@url{https://openmp.org/@/specifications/}).
There also is support for the OpenACC specification (targeting
version 2.6, @uref{https://www.openacc.org/}). See
@uref{https://gcc.gnu.org/wiki/OpenACC} for more information.
@@ -1806,7 +1806,7 @@ It consists of a set of compiler directives, library routines,
and environment variables that influence run-time behavior.
GNU Fortran strives to be compatible to the
-@uref{https://openmp.org/wp/openmp-specifications/,
+@uref{https://openmp.org/specifications/,
OpenMP Application Program Interface v4.5}.
To enable the processing of the OpenMP directive @code{!$omp} in
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 5cbb385..cac11c1 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -27,6 +27,7 @@ CC recognizes how to compile each input file by suffixes in the file names.
Once it knows which kind of compilation to perform, the procedure for
compilation is specified by a string called a "spec". */
+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -43,6 +44,7 @@ compilation is specified by a string called a "spec". */
#include "opts.h"
#include "filenames.h"
#include "spellcheck.h"
+#include "opts-jobserver.h"
@@ -9178,38 +9180,9 @@ driver::final_actions () const
void
driver::detect_jobserver () const
{
- /* Detect jobserver and drop it if it's not working. */
- const char *makeflags = env.get ("MAKEFLAGS");
- if (makeflags != NULL)
- {
- const char *needle = "--jobserver-auth=";
- const char *n = strstr (makeflags, needle);
- if (n != NULL)
- {
- int rfd = -1;
- int wfd = -1;
-
- bool jobserver
- = (sscanf (n + strlen (needle), "%d,%d", &rfd, &wfd) == 2
- && rfd > 0
- && wfd > 0
- && is_valid_fd (rfd)
- && is_valid_fd (wfd));
-
- /* Drop the jobserver if it's not working now. */
- if (!jobserver)
- {
- unsigned offset = n - makeflags;
- char *dup = xstrdup (makeflags);
- dup[offset] = '\0';
-
- const char *space = strchr (makeflags + offset, ' ');
- if (space != NULL)
- strcpy (dup + offset, space);
- xputenv (concat ("MAKEFLAGS=", dup, NULL));
- }
- }
- }
+ jobserver_info jinfo;
+ if (!jinfo.is_active && !jinfo.skipped_makeflags.empty ())
+ xputenv (jinfo.skipped_makeflags.c_str ());
}
/* Determine what the exit code of the driver should be. */
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index 43e7526..78146f5 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -153,38 +153,7 @@ path_range_query::range_on_path_entry (vrange &r, tree name)
{
gcc_checking_assert (defined_outside_path (name));
basic_block entry = entry_bb ();
-
- // Prefer to use range_of_expr if we have a statement to look at,
- // since it has better caching than range_on_edge.
- gimple *last = last_stmt (entry);
- if (last)
- {
- if (m_ranger->range_of_expr (r, name, last))
- return;
- gcc_unreachable ();
- }
-
- // If we have no statement, look at all the incoming ranges to the
- // block. This can happen when we're querying a block with only an
- // outgoing edge (no statement but the fall through edge), but for
- // which we can determine a range on entry to the block.
- Value_Range tmp (TREE_TYPE (name));
- bool changed = false;
- r.set_undefined ();
- for (unsigned i = 0; i < EDGE_COUNT (entry->preds); ++i)
- {
- edge e = EDGE_PRED (entry, i);
- if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
- && m_ranger->range_on_edge (tmp, e, name))
- {
- r.union_ (tmp);
- changed = true;
- }
- }
-
- // Make sure we don't return UNDEFINED by mistake.
- if (!changed)
- r.set_varying (TREE_TYPE (name));
+ m_ranger->range_on_entry (r, entry, name);
}
// Return the range of NAME at the end of the path being analyzed.
@@ -276,8 +245,6 @@ void
path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
{
tree name = gimple_phi_result (phi);
- basic_block bb = gimple_bb (phi);
- unsigned nargs = gimple_phi_num_args (phi);
if (at_entry ())
{
@@ -287,6 +254,7 @@ path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
// Try to fold the phi exclusively with global or cached values.
// This will get things like PHI <5(99), 6(88)>. We do this by
// calling range_of_expr with no context.
+ unsigned nargs = gimple_phi_num_args (phi);
Value_Range arg_range (TREE_TYPE (name));
r.set_undefined ();
for (size_t i = 0; i < nargs; ++i)
@@ -303,36 +271,31 @@ path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
return;
}
+ basic_block bb = gimple_bb (phi);
basic_block prev = prev_bb ();
edge e_in = find_edge (prev, bb);
-
- for (size_t i = 0; i < nargs; ++i)
- if (e_in == gimple_phi_arg_edge (phi, i))
- {
- tree arg = gimple_phi_arg_def (phi, i);
- // Avoid using the cache for ARGs defined in this block, as
- // that could create an ordering problem.
- if (ssa_defined_in_bb (arg, bb) || !get_cache (r, arg))
- {
- if (m_resolve)
- {
- Value_Range tmp (TREE_TYPE (name));
- // Using both the range on entry to the path, and the
- // range on this edge yields significantly better
- // results.
- if (defined_outside_path (arg))
- range_on_path_entry (r, arg);
- else
- r.set_varying (TREE_TYPE (name));
- m_ranger->range_on_edge (tmp, e_in, arg);
- r.intersect (tmp);
- return;
- }
+ tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e_in);
+ // Avoid using the cache for ARGs defined in this block, as
+ // that could create an ordering problem.
+ if (ssa_defined_in_bb (arg, bb) || !get_cache (r, arg))
+ {
+ if (m_resolve)
+ {
+ Value_Range tmp (TREE_TYPE (name));
+ // Using both the range on entry to the path, and the
+ // range on this edge yields significantly better
+ // results.
+ if (TREE_CODE (arg) == SSA_NAME
+ && defined_outside_path (arg))
+ range_on_path_entry (r, arg);
+ else
r.set_varying (TREE_TYPE (name));
- }
- return;
- }
- gcc_unreachable ();
+ m_ranger->range_on_edge (tmp, e_in, arg);
+ r.intersect (tmp);
+ return;
+ }
+ r.set_varying (TREE_TYPE (name));
+ }
}
// If NAME is defined in BB, set R to the range of NAME, and return
@@ -549,7 +512,7 @@ path_range_query::add_to_imports (tree name, bitmap imports)
return false;
}
-// Compute the imports to the path ending in EXIT. These are
+// Compute the imports to PATH. These are
// essentially the SSA names used to calculate the final conditional
// along the path.
//
@@ -559,9 +522,10 @@ path_range_query::add_to_imports (tree name, bitmap imports)
// we can solve.
void
-path_range_query::compute_imports (bitmap imports, basic_block exit)
+path_range_query::compute_imports (bitmap imports, const vec<basic_block> &path)
{
// Start with the imports from the exit block...
+ basic_block exit = path[0];
gori_compute &gori = m_ranger->gori ();
bitmap r_imports = gori.imports (exit);
bitmap_copy (imports, r_imports);
@@ -580,18 +544,11 @@ path_range_query::compute_imports (bitmap imports, basic_block exit)
{
tree name = worklist.pop ();
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+ if (SSA_NAME_IS_DEFAULT_DEF (name)
+ || !path.contains (gimple_bb (def_stmt)))
+ continue;
- if (is_gimple_assign (def_stmt))
- {
- add_to_imports (gimple_assign_rhs1 (def_stmt), imports);
- tree rhs = gimple_assign_rhs2 (def_stmt);
- if (rhs && add_to_imports (rhs, imports))
- worklist.safe_push (rhs);
- rhs = gimple_assign_rhs3 (def_stmt);
- if (rhs && add_to_imports (rhs, imports))
- worklist.safe_push (rhs);
- }
- else if (gphi *phi = dyn_cast <gphi *> (def_stmt))
+ if (gphi *phi = dyn_cast <gphi *> (def_stmt))
{
for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
{
@@ -599,17 +556,41 @@ path_range_query::compute_imports (bitmap imports, basic_block exit)
tree arg = gimple_phi_arg (phi, i)->def;
if (TREE_CODE (arg) == SSA_NAME
- && m_path.contains (e->src)
+ && path.contains (e->src)
&& bitmap_set_bit (imports, SSA_NAME_VERSION (arg)))
worklist.safe_push (arg);
}
}
+ else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
+ {
+ tree ssa[3];
+ if (range_op_handler (ass))
+ {
+ ssa[0] = gimple_range_ssa_p (gimple_range_operand1 (ass));
+ ssa[1] = gimple_range_ssa_p (gimple_range_operand2 (ass));
+ ssa[2] = NULL_TREE;
+ }
+ else if (gimple_assign_rhs_code (ass) == COND_EXPR)
+ {
+ ssa[0] = gimple_range_ssa_p (gimple_assign_rhs1 (ass));
+ ssa[1] = gimple_range_ssa_p (gimple_assign_rhs2 (ass));
+ ssa[2] = gimple_range_ssa_p (gimple_assign_rhs3 (ass));
+ }
+ else
+ continue;
+ for (unsigned j = 0; j < 3; ++j)
+ {
+ tree rhs = ssa[j];
+ if (rhs && add_to_imports (rhs, imports))
+ worklist.safe_push (rhs);
+ }
+ }
}
// Exported booleans along the path, may help conditionals.
if (m_resolve)
- for (i = 0; i < m_path.length (); ++i)
+ for (i = 0; i < path.length (); ++i)
{
- basic_block bb = m_path[i];
+ basic_block bb = path[i];
tree name;
FOR_EACH_GORI_EXPORT_NAME (gori, bb, name)
if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
@@ -636,7 +617,7 @@ path_range_query::compute_ranges (const vec<basic_block> &path,
if (imports)
bitmap_copy (m_imports, imports);
else
- compute_imports (m_imports, exit_bb ());
+ compute_imports (m_imports, m_path);
if (m_resolve)
get_path_oracle ()->reset_path ();
@@ -845,15 +826,9 @@ path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
void
path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
{
- gimple *stmt = last_stmt (bb);
-
- if (stmt
- && gimple_code (stmt) == GIMPLE_COND
- && (import_p (gimple_cond_lhs (stmt))
- || import_p (gimple_cond_rhs (stmt))))
+ if (gcond *cond = safe_dyn_cast <gcond *> (last_stmt (bb)))
{
int_range<2> r;
- gcond *cond = as_a<gcond *> (stmt);
edge e0 = EDGE_SUCC (bb, 0);
edge e1 = EDGE_SUCC (bb, 1);
diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h
index 2c4624e..e783e00 100644
--- a/gcc/gimple-range-path.h
+++ b/gcc/gimple-range-path.h
@@ -37,7 +37,7 @@ public:
void compute_ranges (const vec<basic_block> &,
const bitmap_head *imports = NULL);
void compute_ranges (edge e);
- void compute_imports (bitmap imports, basic_block exit);
+ void compute_imports (bitmap imports, const vec<basic_block> &);
bool range_of_expr (vrange &r, tree name, gimple * = NULL) override;
bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override;
bool unreachable_path_p ();
diff --git a/gcc/gimple-ssa-store-merging.cc b/gcc/gimple-ssa-store-merging.cc
index 0640168..b80b8ea 100644
--- a/gcc/gimple-ssa-store-merging.cc
+++ b/gcc/gimple-ssa-store-merging.cc
@@ -263,7 +263,7 @@ do_shift_rotate (enum tree_code code,
int count)
{
int i, size = TYPE_PRECISION (n->type) / BITS_PER_UNIT;
- unsigned head_marker;
+ uint64_t head_marker;
if (count < 0
|| count >= TYPE_PRECISION (n->type)
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 2e8ab39..eb8efb8 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -3369,6 +3369,20 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
return TRUE;
}
+/* Helper function for noce_convert_multiple_sets_1. If store to
+ DEST can affect P[0] or P[1], clear P[0]. Called via note_stores. */
+
+static void
+check_for_cc_cmp_clobbers (rtx dest, const_rtx, void *p0)
+{
+ rtx *p = (rtx *) p0;
+ if (p[0] == NULL_RTX)
+ return;
+ if (reg_overlap_mentioned_p (dest, p[0])
+ || (p[1] && reg_overlap_mentioned_p (dest, p[1])))
+ p[0] = NULL_RTX;
+}
+
/* This goes through all relevant insns of IF_INFO->then_bb and tries to
create conditional moves. In case a simple move sufficis the insn
should be listed in NEED_NO_CMOV. The rewired-src cases should be
@@ -3519,7 +3533,7 @@ noce_convert_multiple_sets_1 (struct noce_if_info *if_info,
as min/max and emit an insn, accordingly. */
unsigned cost1 = 0, cost2 = 0;
- rtx_insn *seq, *seq1, *seq2;
+ rtx_insn *seq, *seq1, *seq2 = NULL;
rtx temp_dest = NULL_RTX, temp_dest1 = NULL_RTX, temp_dest2 = NULL_RTX;
bool read_comparison = false;
@@ -3531,9 +3545,10 @@ noce_convert_multiple_sets_1 (struct noce_if_info *if_info,
as well. This allows the backend to emit a cmov directly without
creating an additional compare for each. If successful, costing
is easier and this sequence is usually preferred. */
- seq2 = try_emit_cmove_seq (if_info, temp, cond,
- new_val, old_val, need_cmov,
- &cost2, &temp_dest2, cc_cmp, rev_cc_cmp);
+ if (cc_cmp)
+ seq2 = try_emit_cmove_seq (if_info, temp, cond,
+ new_val, old_val, need_cmov,
+ &cost2, &temp_dest2, cc_cmp, rev_cc_cmp);
/* The backend might have created a sequence that uses the
condition. Check this. */
@@ -3588,6 +3603,24 @@ noce_convert_multiple_sets_1 (struct noce_if_info *if_info,
return FALSE;
}
+ if (cc_cmp)
+ {
+ /* Check if SEQ can clobber registers mentioned in
+ cc_cmp and/or rev_cc_cmp. If yes, we need to use
+ only seq1 from that point on. */
+ rtx cc_cmp_pair[2] = { cc_cmp, rev_cc_cmp };
+ for (walk = seq; walk; walk = NEXT_INSN (walk))
+ {
+ note_stores (walk, check_for_cc_cmp_clobbers, cc_cmp_pair);
+ if (cc_cmp_pair[0] == NULL_RTX)
+ {
+ cc_cmp = NULL_RTX;
+ rev_cc_cmp = NULL_RTX;
+ break;
+ }
+ }
+ }
+
/* End the sub sequence and emit to the main sequence. */
emit_insn (seq);
diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
index 412ca14..265d07b 100644
--- a/gcc/ipa-devirt.cc
+++ b/gcc/ipa-devirt.cc
@@ -285,6 +285,19 @@ type_possibly_instantiated_p (tree t)
return vnode && vnode->definition;
}
+/* Return true if T or type derived from T may have instance. */
+
+static bool
+type_or_derived_type_possibly_instantiated_p (odr_type t)
+{
+ if (type_possibly_instantiated_p (t->type))
+ return true;
+ for (auto derived : t->derived_types)
+ if (type_or_derived_type_possibly_instantiated_p (derived))
+ return true;
+ return false;
+}
+
/* Hash used to unify ODR types based on their mangled name and for anonymous
namespace types. */
@@ -3172,6 +3185,7 @@ possible_polymorphic_call_targets (tree otr_type,
{
odr_type speculative_outer_type;
bool speculation_complete = true;
+ bool check_derived_types = false;
/* First insert target from type itself and check if it may have
derived types. */
@@ -3190,8 +3204,12 @@ possible_polymorphic_call_targets (tree otr_type,
to walk derivations. */
if (target && DECL_FINAL_P (target))
context.speculative_maybe_derived_type = false;
- if (type_possibly_instantiated_p (speculative_outer_type->type))
- maybe_record_node (nodes, target, &inserted, can_refer, &speculation_complete);
+ if (check_derived_types
+ ? type_or_derived_type_possibly_instantiated_p
+ (speculative_outer_type)
+ : type_possibly_instantiated_p (speculative_outer_type->type))
+ maybe_record_node (nodes, target, &inserted, can_refer,
+ &speculation_complete);
if (binfo)
matched_vtables.add (BINFO_VTABLE (binfo));
@@ -3212,6 +3230,7 @@ possible_polymorphic_call_targets (tree otr_type,
if (!speculative || !nodes.length ())
{
+ bool check_derived_types = false;
/* First see virtual method of type itself. */
binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
context.offset, otr_type);
@@ -3229,16 +3248,18 @@ possible_polymorphic_call_targets (tree otr_type,
if (target && DECL_CXX_DESTRUCTOR_P (target))
context.maybe_in_construction = false;
- if (target)
+ /* In the case we get complete method, we don't need
+ to walk derivations. */
+ if (target && DECL_FINAL_P (target))
{
- /* In the case we get complete method, we don't need
- to walk derivations. */
- if (DECL_FINAL_P (target))
- context.maybe_derived_type = false;
+ check_derived_types = true;
+ context.maybe_derived_type = false;
}
/* If OUTER_TYPE is abstract, we know we are not seeing its instance. */
- if (type_possibly_instantiated_p (outer_type->type))
+ if (check_derived_types
+ ? type_or_derived_type_possibly_instantiated_p (outer_type)
+ : type_possibly_instantiated_p (outer_type->type))
maybe_record_node (nodes, target, &inserted, can_refer, &complete);
else
skipped = true;
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
index 795ab74..1e8eba1 100644
--- a/gcc/lto-wrapper.cc
+++ b/gcc/lto-wrapper.cc
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
./ccCJuXGv.lto.ltrans.o
*/
+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -49,6 +50,8 @@ along with GCC; see the file COPYING3. If not see
#include "lto-section-names.h"
#include "collect-utils.h"
#include "opts-diagnostic.h"
+#include "opt-suggestions.h"
+#include "opts-jobserver.h"
/* Environment variable, used for passing the names of offload targets from GCC
driver to lto-wrapper. */
@@ -1336,35 +1339,6 @@ init_num_threads (void)
#endif
}
-/* Test and return reason why a jobserver cannot be detected. */
-
-static const char *
-jobserver_active_p (void)
-{
- #define JS_PREFIX "jobserver is not available: "
- #define JS_NEEDLE "--jobserver-auth="
-
- const char *makeflags = getenv ("MAKEFLAGS");
- if (makeflags == NULL)
- return JS_PREFIX "%<MAKEFLAGS%> environment variable is unset";
-
- const char *n = strstr (makeflags, JS_NEEDLE);
- if (n == NULL)
- return JS_PREFIX "%<" JS_NEEDLE "%> is not present in %<MAKEFLAGS%>";
-
- int rfd = -1;
- int wfd = -1;
-
- if (sscanf (n + strlen (JS_NEEDLE), "%d,%d", &rfd, &wfd) == 2
- && rfd > 0
- && wfd > 0
- && is_valid_fd (rfd)
- && is_valid_fd (wfd))
- return NULL;
- else
- return JS_PREFIX "cannot access %<" JS_NEEDLE "%> file descriptors";
-}
-
/* Print link to -flto documentation with a hint message. */
void
@@ -1422,7 +1396,6 @@ run_gcc (unsigned argc, char *argv[])
bool jobserver_requested = false;
int auto_parallel = 0;
bool no_partition = false;
- const char *jobserver_error = NULL;
bool fdecoded_options_first = true;
vec<cl_decoded_option> fdecoded_options;
fdecoded_options.create (16);
@@ -1653,14 +1626,14 @@ run_gcc (unsigned argc, char *argv[])
}
else
{
- jobserver_error = jobserver_active_p ();
- if (jobserver && jobserver_error != NULL)
+ jobserver_info jinfo;
+ if (jobserver && !jinfo.is_active)
{
/* Fall back to auto parallelism. */
jobserver = 0;
auto_parallel = 1;
}
- else if (!jobserver && jobserver_error == NULL)
+ else if (!jobserver && jinfo.is_active)
{
parallel = 1;
jobserver = 1;
@@ -1971,9 +1944,10 @@ cont:
if (nr > 1)
{
- if (jobserver_requested && jobserver_error != NULL)
+ jobserver_info jinfo;
+ if (jobserver_requested && !jinfo.is_active)
{
- warning (0, jobserver_error);
+ warning (0, jinfo.error_msg.c_str ());
print_lto_docs_link ();
}
else if (parallel == 0)
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 3cf57fa..eae6dae 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,11 @@
+2022-08-10 Martin Liska <mliska@suse.cz>
+
+ PR lto/106328
+ * lto.cc (wait_for_child): Decrement nruns once a process
+ finishes.
+ (stream_out_partitions): Use job server if active.
+ (do_whole_program_analysis): Likewise.
+
2022-07-08 Martin Liska <mliska@suse.cz>
* lto-dump.cc (lto_main): Exit in the function
diff --git a/gcc/lto/lto.cc b/gcc/lto/lto.cc
index 31b0c18..c82307f 100644
--- a/gcc/lto/lto.cc
+++ b/gcc/lto/lto.cc
@@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -54,11 +55,17 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "builtins.h"
#include "lto-common.h"
+#include "opts-jobserver.h"
-
-/* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */
+/* Number of parallel tasks to run. */
static int lto_parallelism;
+/* Number of active WPA streaming processes. */
+static int nruns = 0;
+
+/* GNU make's jobserver info. */
+static jobserver_info *jinfo = NULL;
+
/* Return true when NODE has a clone that is analyzed (i.e. we need
to load its body even if the node itself is not needed). */
@@ -205,6 +212,12 @@ wait_for_child ()
"streaming subprocess was killed by signal");
}
while (!WIFEXITED (status) && !WIFSIGNALED (status));
+
+ --nruns;
+
+ /* Return token to the jobserver if active. */
+ if (jinfo != NULL && jinfo->is_active)
+ jinfo->return_token ();
}
#endif
@@ -228,25 +241,35 @@ stream_out_partitions (char *temp_filename, int blen, int min, int max,
bool ARG_UNUSED (last))
{
#ifdef HAVE_WORKING_FORK
- static int nruns;
-
if (lto_parallelism <= 1)
{
stream_out_partitions_1 (temp_filename, blen, min, max);
return;
}
- /* Do not run more than LTO_PARALLELISM streamings
- FIXME: we ignore limits on jobserver. */
if (lto_parallelism > 0 && nruns >= lto_parallelism)
- {
- wait_for_child ();
- nruns --;
- }
+ wait_for_child ();
+
/* If this is not the last parallel partition, execute new
streaming process. */
if (!last)
{
+ if (jinfo != NULL && jinfo->is_active)
+ while (true)
+ {
+ if (jinfo->get_token ())
+ break;
+ if (nruns > 0)
+ wait_for_child ();
+ else
+ {
+ /* There are no free tokens, lets do the job outselves. */
+ stream_out_partitions_1 (temp_filename, blen, min, max);
+ asm_nodes_output = true;
+ return;
+ }
+ }
+
pid_t cpid = fork ();
if (!cpid)
@@ -264,10 +287,12 @@ stream_out_partitions (char *temp_filename, int blen, int min, int max,
/* Last partition; stream it and wait for all children to die. */
else
{
- int i;
stream_out_partitions_1 (temp_filename, blen, min, max);
- for (i = 0; i < nruns; i++)
+ while (nruns > 0)
wait_for_child ();
+
+ if (jinfo != NULL && jinfo->is_active)
+ jinfo->disconnect ();
}
asm_nodes_output = true;
#else
@@ -460,9 +485,14 @@ do_whole_program_analysis (void)
lto_parallelism = 1;
- /* TODO: jobserver communication is not supported, yet. */
if (!strcmp (flag_wpa, "jobserver"))
- lto_parallelism = param_max_lto_streaming_parallelism;
+ {
+ jinfo = new jobserver_info ();
+ if (jinfo->is_active)
+ jinfo->connect ();
+
+ lto_parallelism = param_max_lto_streaming_parallelism;
+ }
else
{
lto_parallelism = atoi (flag_wpa);
diff --git a/gcc/match.pd b/gcc/match.pd
index c22bc2c..e32bda6 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -982,6 +982,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(lshift @0 @2)))
+/* Shifts by constants distribute over several binary operations,
+ hence (X << C) + (Y << C) can be simplified to (X + Y) << C. */
+(for op (plus minus)
+ (simplify
+ (op (lshift:s @0 @1) (lshift:s @2 @1))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type)
+ && !TYPE_SATURATING (type))
+ (lshift (op @0 @2) @1))))
+
+(for op (bit_and bit_ior bit_xor)
+ (simplify
+ (op (lshift:s @0 @1) (lshift:s @2 @1))
+ (if (INTEGRAL_TYPE_P (type))
+ (lshift (op @0 @2) @1)))
+ (simplify
+ (op (rshift:s @0 @1) (rshift:s @2 @1))
+ (if (INTEGRAL_TYPE_P (type))
+ (rshift (op @0 @2) @1))))
+
/* Fold (1 << (C - x)) where C = precision(type) - 1
into ((1 << C) >> x). */
(simplify
@@ -1900,6 +1920,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0)))
(mult (convert @1) (convert @2))))
+/* (X << C) != 0 can be simplified to X, when C is zero_one_valued_p.
+ Check that the shift is well-defined (C is less than TYPE_PRECISION)
+ as some targets (such as x86's SSE) may return zero for larger C. */
+(simplify
+ (ne (lshift zero_one_valued_p@0 INTEGER_CST@1) integer_zerop@2)
+ (if (tree_fits_shwi_p (@1)
+ && tree_to_shwi (@1) > 0
+ && tree_to_shwi (@1) < TYPE_PRECISION (TREE_TYPE (@0)))
+ (convert @0)))
+
+/* (X << C) == 0 can be simplified to X == 0, when C is zero_one_valued_p.
+ Check that the shift is well-defined (C is less than TYPE_PRECISION)
+ as some targets (such as x86's SSE) may return zero for larger C. */
+(simplify
+ (eq (lshift zero_one_valued_p@0 INTEGER_CST@1) integer_zerop@2)
+ (if (tree_fits_shwi_p (@1)
+ && tree_to_shwi (@1) > 0
+ && tree_to_shwi (@1) < TYPE_PRECISION (TREE_TYPE (@0)))
+ (eq @0 @2)))
+
/* Convert ~ (-A) to A - 1. */
(simplify
(bit_not (convert? (negate @0)))
diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
index 8097c05..4dec9f9 100644
--- a/gcc/opts-common.cc
+++ b/gcc/opts-common.cc
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "intl.h"
@@ -25,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "options.h"
#include "diagnostic.h"
#include "spellcheck.h"
+#include "opts-jobserver.h"
static void prune_options (struct cl_decoded_option **, unsigned int *);
@@ -2005,3 +2007,95 @@ void prepend_xassembler_to_collect_as_options (const char *collect_as_options,
obstack_1grow (o, '\'');
}
}
+
+jobserver_info::jobserver_info ()
+{
+ /* Traditionally, GNU make uses opened pipes for jobserver-auth,
+ e.g. --jobserver-auth=3,4.
+ Starting with GNU make 4.4, one can use --jobserver-style=fifo
+ and then named pipe is used: --jobserver-auth=fifo:/tmp/hcsparta. */
+
+ /* Detect jobserver and drop it if it's not working. */
+ string js_needle = "--jobserver-auth=";
+ string fifo_prefix = "fifo:";
+
+ const char *envval = getenv ("MAKEFLAGS");
+ if (envval != NULL)
+ {
+ string makeflags = envval;
+ size_t n = makeflags.rfind (js_needle);
+ if (n != string::npos)
+ {
+ string ending = makeflags.substr (n + js_needle.size ());
+ if (ending.find (fifo_prefix) == 0)
+ {
+ ending = ending.substr (fifo_prefix.size ());
+ pipe_path = ending.substr (0, ending.find (' '));
+ is_active = true;
+ }
+ else if (sscanf (makeflags.c_str () + n + js_needle.size (),
+ "%d,%d", &rfd, &wfd) == 2
+ && rfd > 0
+ && wfd > 0
+ && is_valid_fd (rfd)
+ && is_valid_fd (wfd))
+ is_active = true;
+ else
+ {
+ string dup = makeflags.substr (0, n);
+ size_t pos = makeflags.find (' ', n);
+ if (pos != string::npos)
+ dup += makeflags.substr (pos);
+ skipped_makeflags = "MAKEFLAGS=" + dup;
+ error_msg
+ = "cannot access %<" + js_needle + "%> file descriptors";
+ }
+ }
+ error_msg = "%<" + js_needle + "%> is not present in %<MAKEFLAGS%>";
+ }
+ else
+ error_msg = "%<MAKEFLAGS%> environment variable is unset";
+
+ if (!error_msg.empty ())
+ error_msg = "jobserver is not available: " + error_msg;
+}
+
+void
+jobserver_info::connect ()
+{
+ if (!pipe_path.empty ())
+ pipefd = open (pipe_path.c_str (), O_RDWR | O_NONBLOCK);
+}
+
+void
+jobserver_info::disconnect ()
+{
+ if (!pipe_path.empty ())
+ {
+ gcc_assert (close (pipefd) == 0);
+ pipefd = -1;
+ }
+}
+
+bool
+jobserver_info::get_token ()
+{
+ int fd = pipe_path.empty () ? rfd : pipefd;
+ char c;
+ unsigned n = read (fd, &c, 1);
+ if (n != 1)
+ {
+ gcc_assert (errno == EAGAIN);
+ return false;
+ }
+ else
+ return true;
+}
+
+void
+jobserver_info::return_token ()
+{
+ int fd = pipe_path.empty () ? wfd : pipefd;
+ char c = 'G';
+ gcc_assert (write (fd, &c, 1) == 1);
+}
diff --git a/gcc/opts-jobserver.h b/gcc/opts-jobserver.h
new file mode 100644
index 0000000..76c1d9b
--- /dev/null
+++ b/gcc/opts-jobserver.h
@@ -0,0 +1,60 @@
+/* GNU make's jobserver related functionality.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>.
+
+See dbgcnt.def for usage information. */
+
+#ifndef GCC_JOBSERVER_H
+#define GCC_JOBSERVER_H
+
+using namespace std;
+
+struct jobserver_info
+{
+ /* Default constructor. */
+ jobserver_info ();
+
+ /* Connect to the server. */
+ void connect ();
+
+ /* Disconnect from the server. */
+ void disconnect ();
+
+ /* Get token from the server. */
+ bool get_token ();
+
+ /* Return token to the server. */
+ void return_token ();
+
+ /* Error message if there is a problem. */
+ string error_msg = "";
+ /* Skipped MAKEFLAGS where --jobserver-auth is skipped. */
+ string skipped_makeflags = "";
+ /* File descriptor for reading used for jobserver communication. */
+ int rfd = -1;
+ /* File descriptor for writing used for jobserver communication. */
+ int wfd = -1;
+ /* Named pipe path. */
+ string pipe_path = "";
+ /* Pipe file descriptor. */
+ int pipefd = -1;
+ /* Return true if jobserver is active. */
+ bool is_active = false;
+};
+
+#endif /* GCC_JOBSERVER_H */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9a31d8d..7379a89 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,255 @@
+2022-08-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/106623
+ * gdc.dg/torture/pr106623.d: New test.
+
+2022-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/106626
+ * gcc.dg/analyzer/out-of-bounds-read-char-arr.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-read-int-arr.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-write-char-arr.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-write-int-arr.c: New test.
+
+2022-08-15 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/106621
+ * gcc.dg/pr106621.c
+
+2022-08-15 Immad Mir <mirimmad@outlook.com>
+
+ PR analyzer/106551
+ * gcc.dg/analyzer/fd-dup-1.c: New testcase.
+
+2022-08-15 Roger Sayle <roger@nextmovesoftware.com>
+
+ * gcc.target/i386/sse4_1-stv-9.c: New test case.
+
+2022-08-15 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR tree-optimization/64992
+ * gcc.dg/pr64992.c: New test case.
+
+2022-08-15 Roger Sayle <roger@nextmovesoftware.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/71343
+ * gcc.dg/pr71343-1.c: New test case.
+
+2022-08-15 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/modules/loc-prune-4.C: Adjust regexp
+
+2022-08-15 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106276
+ * g++.dg/cpp0x/Wpessimizing-move7.C: New test.
+
+2022-08-15 Alexandre Oliva <oliva@adacore.com>
+
+ * g++.dg/abi/anon1.C: Disable pie on ia32.
+ * g++.dg/abi/anon4.C: Likewise.
+ * g++.dg/cpp0x/initlist-const1.C: Likewise.
+ * g++.dg/no-stack-protector-attr-3.C: Likewise.
+ * g++.dg/stackprotectexplicit2.C: Likewise.
+ * g++.dg/pr71694.C: Likewise.
+ * gcc.dg/pr102892-1.c: Likewise.
+ * gcc.dg/sibcall-11.c: Likewise.
+ * gcc.dg/torture/builtin-self.c: Likewise.
+ * gcc.target/i386/avx2-dest-false-dep-for-glc.c: Likewise.
+ * gcc.target/i386/avx512bf16-cvtsbh2ss-1.c: Likewise.
+ * gcc.target/i386/avx512f-broadcast-pr87767-1.c: Likewise.
+ * gcc.target/i386/avx512f-broadcast-pr87767-3.c: Likewise.
+ * gcc.target/i386/avx512f-broadcast-pr87767-5.c: Likewise.
+ * gcc.target/i386/avx512f-broadcast-pr87767-7.c: Likewise.
+ * gcc.target/i386/avx512fp16-broadcast-1.c: Likewise.
+ * gcc.target/i386/avx512fp16-pr101846.c: Likewise.
+ * gcc.target/i386/avx512vl-broadcast-pr87767-1.c: Likewise.
+ * gcc.target/i386/avx512vl-broadcast-pr87767-3.c: Likewise.
+ * gcc.target/i386/avx512vl-broadcast-pr87767-5.c: Likewise.
+ * gcc.target/i386/pr100865-2.c: Likewise.
+ * gcc.target/i386/pr100865-3.c: Likewise.
+ * gcc.target/i386/pr100865-4a.c: Likewise.
+ * gcc.target/i386/pr100865-4b.c: Likewise.
+ * gcc.target/i386/pr100865-5a.c: Likewise.
+ * gcc.target/i386/pr100865-5b.c: Likewise.
+ * gcc.target/i386/pr100865-6a.c: Likewise.
+ * gcc.target/i386/pr100865-6b.c: Likewise.
+ * gcc.target/i386/pr100865-6c.c: Likewise.
+ * gcc.target/i386/pr100865-7b.c: Likewise.
+ * gcc.target/i386/pr101796-1.c: Likewise.
+ * gcc.target/i386/pr101846-2.c: Likewise.
+ * gcc.target/i386/pr101989-broadcast-1.c: Likewise.
+ * gcc.target/i386/pr102021.c: Likewise.
+ * gcc.target/i386/pr90773-17.c: Likewise.
+ * gcc.target/i386/pr54855-3.c: Likewise.
+ * gcc.target/i386/pr54855-7.c: Likewise.
+ * gcc.target/i386/pr15184-1.c: Likewise.
+ * gcc.target/i386/pr15184-2.c: Likewise.
+ * gcc.target/i386/pr27971.c: Likewise.
+ * gcc.target/i386/pr70263-2.c: Likewise.
+ * gcc.target/i386/pr78035.c: Likewise.
+ * gcc.target/i386/pr81736-5.c: Likewise.
+ * gcc.target/i386/pr81736-7.c: Likewise.
+ * gcc.target/i386/pr85620-6.c: Likewise.
+ * gcc.target/i386/pr85667-6.c: Likewise.
+ * gcc.target/i386/pr93492-5.c: Likewise.
+ * gcc.target/i386/pr96539.c: Likewise.
+ PR target/81708 (%gs:my_guard)
+ * gcc.target/i386/stack-prot-sym.c: Likewise.
+ * g++.dg/init/static-cdtor1.C: Add alternate patterns for PIC.
+ * gcc.target/i386/avx512fp16-vcvtsh2si-1a.c: Extend patterns
+ for PIC/PIE register allocation.
+ * gcc.target/i386/pr100704-3.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttsh2si-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vmovsh-1a.c: Likewise.
+ * gcc.target/i386/interrupt-11.c: Likewise, allowing for
+ preservation of the PIC register.
+ * gcc.target/i386/interrupt-12.c: Likewise.
+ * gcc.target/i386/interrupt-13.c: Likewise.
+ * gcc.target/i386/interrupt-15.c: Likewise.
+ * gcc.target/i386/interrupt-16.c: Likewise.
+ * gcc.target/i386/interrupt-17.c: Likewise.
+ * gcc.target/i386/interrupt-8.c: Likewise.
+ * gcc.target/i386/cet-sjlj-6a.c: Combine patterns from
+ previous change.
+ * gcc.target/i386/cet-sjlj-6b.c: Likewise.
+ * gcc.target/i386/pad-10.c: Accept insns in get_pc_thunk.
+ * gcc.target/i386/pr70321.c: Likewise.
+ * gcc.target/i386/pr81563.c: Likewise.
+ * gcc.target/i386/pr84278.c: Likewise.
+ * gcc.target/i386/pr90773-2.c: Likewise, plus extra loads from
+ the GOT.
+ * gcc.target/i386/pr90773-3.c: Likewise.
+ * gcc.target/i386/pr94913-2.c: Accept additional PIC insns.
+ * gcc.target/i386/stack-check-17.c: Likewise.
+ * gcc.target/i386/stack-check-12.c: Do not require dummy stack
+ probing obviated with PIC.
+ * gcc.target/i386/pr95126-m32-1.c: Expect missed optimization
+ with PIC.
+ * gcc.target/i386/pr95126-m32-2.c: Likewise.
+ * gcc.target/i386/pr95852-2.c: Accept different optimization
+ with PIC.
+ * gcc.target/i386/pr95852-4.c: Likewise.
+
+2022-08-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/106590
+ * gcc.dg/torture/pr106590.c: New test.
+
+2022-08-15 konglin1 <lingling.kong@intel.com>
+
+ * g++.target/i386/bfloat_cpp_typecheck.C: New test.
+ * gcc.target/i386/bfloat16-1.c: Ditto.
+ * gcc.target/i386/sse2-bfloat16-1.c: Ditto.
+ * gcc.target/i386/sse2-bfloat16-2.c: Ditto.
+ * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Ditto.
+
+2022-08-13 Tim Lange <mail@tim-lange.me>
+
+ * gcc.dg/analyzer/torture/pr93451.c:
+ Disable Wanalyzer-out-of-bounds.
+
+2022-08-12 Jan Hubicka <hubicka@ucw.cz>
+
+ PR middle-end/106057
+ * g++.dg/tree-ssa/pr101839.C: New test.
+
+2022-08-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/106506
+ * g++.dg/opt/pr94589-2.C: New test.
+
+2022-08-12 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/106524
+ * gcc.target/aarch64/sve/pr106524.c: New test.
+
+2022-08-12 Tim Lange <mail@tim-lange.me>
+
+ PR analyzer/106000
+ * g++.dg/analyzer/pr100244.C: Disable out-of-bounds warning.
+ * gcc.dg/analyzer/allocation-size-3.c:
+ Disable out-of-bounds warning.
+ * gcc.dg/analyzer/memcpy-2.c: Disable out-of-bounds warning.
+ * gcc.dg/analyzer/pr101962.c: Add dg-warning.
+ * gcc.dg/analyzer/pr96764.c: Disable out-of-bounds warning.
+ * gcc.dg/analyzer/pr97029.c:
+ Add dummy buffer to prevent an out-of-bounds warning.
+ * gcc.dg/analyzer/realloc-5.c: Add dg-warning.
+ * gcc.dg/analyzer/test-setjmp.h:
+ Add dummy buffer to prevent an out-of-bounds warning.
+ * gcc.dg/analyzer/zlib-3.c: Add dg-bogus.
+ * g++.dg/analyzer/out-of-bounds-placement-new.C: New test.
+ * gcc.dg/analyzer/out-of-bounds-1.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-2.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-3.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-container_of.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-coreutils.c: New test.
+ * gcc.dg/analyzer/out-of-bounds-curl.c: New test.
+
+2022-08-12 Tim Lange <mail@tim-lange.me>
+
+ PR analyzer/106539
+ * gcc.dg/analyzer/pr106539.c: New test.
+ * gcc.dg/analyzer/realloc-5.c: New test.
+
+2022-08-11 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/analyzer/fd-4.c: Define _MODE_T on AIX.
+
+2022-08-11 David Edelsohn <dje.gcc@gmail.com>
+
+ * g++.dg/cpp0x/initlist-const1.C: XFAIL on AIX.
+
+2022-08-11 Immad Mir <mirimmad@outlook.com>
+
+ * gcc.dg/analyzer/fd-dup-1.c: New testcases.
+ * gcc.dg/analyzer/fd-uninit-1.c: Remove bogus
+ warning.
+
+2022-08-11 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/102633
+ * c-c++-common/Winit-self1.c: New test.
+ * c-c++-common/Winit-self2.c: New test.
+
+2022-08-11 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106514
+ * gcc.dg/tree-ssa/ssa-thread-19.c: Un-XFAIL.
+ * gcc.dg/tree-ssa/ssa-thread-20.c: New testcase.
+
+2022-08-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/106243
+ * gcc.dg/pr106243.c: Add -Wno-psabi to dg-options.
+ * gcc.dg/pr106243-1.c: Likewise.
+
+2022-08-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/104992
+ * gcc.dg/pr104992.c: Add -Wno-psabi to dg-options.
+ * g++.dg/pr104992-1.C: Likewise. Add space between " and } in
+ dg-options.
+
+2022-08-11 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-thread-18.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-thread-19.c: Likewise, but XFAILed.
+
+2022-08-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/106513
+ * gcc.dg/torture/pr106513.c: New testcase.
+
+2022-08-10 Roger Sayle <roger@nextmovesoftware.com>
+
+ PR other/106575
+ * gcc.dg/fold-eqandshift-4.c: Use "signed char" explicitly.
+
2022-08-09 David Malcolm <dmalcolm@redhat.com>
PR analyzer/106573
diff --git a/gcc/testsuite/c-c++-common/Winit-self1.c b/gcc/testsuite/c-c++-common/Winit-self1.c
new file mode 100644
index 0000000..740b83b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Winit-self1.c
@@ -0,0 +1,31 @@
+/* PR middle-end/102633 */
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -Wno-init-self" } */
+
+int
+fn1 (void)
+{
+ int i = i;
+ return i;
+}
+
+int
+fn2 ()
+{
+ const int j = j;
+ return j;
+}
+
+int
+fn3 ()
+{
+ volatile int k = k;
+ return k;
+}
+
+int
+fn4 ()
+{
+ const volatile int l = l;
+ return l;
+}
diff --git a/gcc/testsuite/c-c++-common/Winit-self2.c b/gcc/testsuite/c-c++-common/Winit-self2.c
new file mode 100644
index 0000000..13aa9ef
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Winit-self2.c
@@ -0,0 +1,31 @@
+/* PR middle-end/102633 */
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -Winit-self" } */
+
+int
+fn1 (void)
+{
+ int i = i; /* { dg-warning "used uninitialized" } */
+ return i;
+}
+
+int
+fn2 ()
+{
+ const int j = j; /* { dg-warning "used uninitialized" } */
+ return j;
+}
+
+int
+fn3 ()
+{
+ volatile int k = k; /* { dg-warning "used uninitialized" } */
+ return k;
+}
+
+int
+fn4 ()
+{
+ const volatile int l = l; /* { dg-warning "used uninitialized" } */
+ return l;
+}
diff --git a/gcc/testsuite/g++.dg/abi/anon1.C b/gcc/testsuite/g++.dg/abi/anon1.C
index 0fb4ae8..52018c3 100644
--- a/gcc/testsuite/g++.dg/abi/anon1.C
+++ b/gcc/testsuite/g++.dg/abi/anon1.C
@@ -1,4 +1,5 @@
// PR c++/54883
+// { dg-additional-options "-fno-pie" { target ia32 } }
namespace { enum E { E1 }; } void f(E e) { }
diff --git a/gcc/testsuite/g++.dg/abi/anon4.C b/gcc/testsuite/g++.dg/abi/anon4.C
index 8200f4b..517cc52 100644
--- a/gcc/testsuite/g++.dg/abi/anon4.C
+++ b/gcc/testsuite/g++.dg/abi/anon4.C
@@ -1,5 +1,5 @@
// PR c++/65209
-// { dg-additional-options "-fno-pie" { target sparc*-*-* } }
+// { dg-additional-options "-fno-pie" { target { ia32 || sparc*-*-* } } }
// { dg-final { scan-assembler-not "comdat" } }
// Everything involving the anonymous namespace bits should be private, not
diff --git a/gcc/testsuite/g++.dg/analyzer/out-of-bounds-placement-new.C b/gcc/testsuite/g++.dg/analyzer/out-of-bounds-placement-new.C
new file mode 100644
index 0000000..d3076c3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/out-of-bounds-placement-new.C
@@ -0,0 +1,19 @@
+/* Reduced from pr100244.C. */
+inline void *operator new (__SIZE_TYPE__, void *__p) { return __p; }
+
+struct int_container {
+ int i;
+ int *addr () { return &i; }
+};
+
+struct int_and_addr {
+ int i;
+ int *addr;
+ int_and_addr () { addr = &i; } /* { dg-warning "overflow" } */
+};
+
+int test (int_container ic)
+{
+ int_and_addr *iaddr = new (ic.addr ()) int_and_addr;
+ return iaddr->i;
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/pr100244.C b/gcc/testsuite/g++.dg/analyzer/pr100244.C
index 1d5e13d..6e2ac4c 100644
--- a/gcc/testsuite/g++.dg/analyzer/pr100244.C
+++ b/gcc/testsuite/g++.dg/analyzer/pr100244.C
@@ -1,4 +1,7 @@
-// { dg-additional-options "-O1 -Wno-free-nonheap-object" }
+// { dg-additional-options "-O1 -Wno-free-nonheap-object -Wno-analyzer-out-of-bounds" }
+/* Disabled out-of-bounds checker because the output relied
+ on optimizations. out-of-bounds-placement-new.C tests
+ the same pattern but without optimizations. */
inline void *operator new (__SIZE_TYPE__, void *__p) { return __p; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C
new file mode 100644
index 0000000..cd4eaa0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C
@@ -0,0 +1,63 @@
+// PR c++/106276
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct A { A(); A(const A&) = delete; A(A&&); };
+struct B { B(A); };
+
+static A foo ();
+
+A
+fn1 ()
+{
+ return std::move (A{}); // { dg-warning "moving a temporary object in a return statement prevents copy elision" }
+ return std::move (A()); // { dg-warning "moving a temporary object in a return statement prevents copy elision" }
+ return std::move (foo ()); // { dg-warning "moving a temporary object in a return statement prevents copy elision" }
+}
+
+B fn2 ()
+{
+ return std::move (A());
+ return std::move (A{});
+ return std::move (foo ());
+}
+
+template <typename T1, typename T2>
+T1
+fn3 ()
+{
+ return std::move (T2{}); // { dg-warning "moving a temporary object in a return statement prevents copy elision" }
+}
+
+void
+do_fn3 ()
+{
+ fn3<A, A>();
+ fn3<B, A>();
+}
+
+char take_buffer;
+struct label_text {
+ label_text take() { return std::move(label_text(&take_buffer)); } // { dg-warning "moving a temporary object in a return statement prevents copy elision" }
+ label_text(char *);
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C
index de80731..0da0759 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C
@@ -1,7 +1,9 @@
// { dg-do compile { target c++11 } }
+/* PIC uses .data.rel.ro.local rather than .rodata. */
+/* { dg-additional-options "-fno-PIE" } */
#include <initializer_list>
const auto x = { 1, 2 };
-// { dg-final { scan-assembler-not {\.data} } }
+// { dg-final { scan-assembler-not {\.data} { xfail powerpc-ibm-aix* } } }
diff --git a/gcc/testsuite/g++.dg/init/static-cdtor1.C b/gcc/testsuite/g++.dg/init/static-cdtor1.C
index 343178a..d4d85f9 100644
--- a/gcc/testsuite/g++.dg/init/static-cdtor1.C
+++ b/gcc/testsuite/g++.dg/init/static-cdtor1.C
@@ -3,9 +3,11 @@
// Make sure we emit initializers in the correct order.
// ctors
-// { dg-final { scan-assembler {_Z41__static_initialization_and_destruction_0v:.*movl \$var1[^\n]*\n[^\n]*_ZN5LeelaC1Ev[^\n]*\n[^\n]*movl \$var2[^\n]*\n[^\n]*_ZN5LeelaC1Ev[^\n]*\n[^\n]*movl \$var3[^\n]*\n[^\n]*_ZN5LeelaC1Ev} } }
+// { dg-final { scan-assembler {_Z41__static_initialization_and_destruction_0v:.*movl \$var1[^\n]*\n[^\n]*_ZN5LeelaC1Ev[^\n]*\n[^\n]*movl \$var2[^\n]*\n[^\n]*_ZN5LeelaC1Ev[^\n]*\n[^\n]*movl \$var3[^\n]*\n[^\n]*_ZN5LeelaC1Ev} { target nonpic } } }
+// { dg-final { scan-assembler {_Z41__static_initialization_and_destruction_0v:.*leaq var1[^\n]*\n[^\n]*(?:|movq[^\n]*\n[^\n]*)_ZN5LeelaC1Ev[^\n]*\n[^\n]*leaq var2[^\n]*\n[^\n]*(?:|movq[^\n]*\n[^\n]*)_ZN5LeelaC1Ev[^\n]*\n[^\n]*leaq var3[^\n]*\n[^\n]*(?:|movq[^\n]*\n[^\n]*)_ZN5LeelaC1Ev} { target { ! nonpic } } } }
// dtors
-// { dg-final { scan-assembler {_Z41__static_initialization_and_destruction_1v:.*movl \$var3[^\n]*\n[^\n]*_ZN5LeelaD1Ev[^\n]*\n[^\n]*movl \$var2[^\n]*\n[^\n]*_ZN5LeelaD1Ev[^\n]*\n[^\n]*movl \$var1[^\n]*\n[^\n]*_ZN5LeelaD1Ev} } }
+// { dg-final { scan-assembler {_Z41__static_initialization_and_destruction_1v:.*movl \$var3[^\n]*\n[^\n]*_ZN5LeelaD1Ev[^\n]*\n[^\n]*movl \$var2[^\n]*\n[^\n]*_ZN5LeelaD1Ev[^\n]*\n[^\n]*movl \$var1[^\n]*\n[^\n]*_ZN5LeelaD1Ev} { target nonpic } } }
+// { dg-final { scan-assembler {_Z41__static_initialization_and_destruction_1v:.*leaq var3[^\n]*\n[^\n]*(?:|movq[^\n]*\n[^\n]*)_ZN5LeelaD1Ev[^\n]*\n[^\n]*leaq var2[^\n]*\n[^\n]*(?:|movq[^\n]*\n[^\n]*)_ZN5LeelaD1Ev[^\n]*\n[^\n]*leaq var1[^\n]*\n[^\n]*(?:|movq[^\n]*\n[^\n]*)_ZN5LeelaD1Ev} { target { ! nonpic } } } }
struct Leela {
Leela ();
diff --git a/gcc/testsuite/g++.dg/modules/loc-prune-4.C b/gcc/testsuite/g++.dg/modules/loc-prune-4.C
index 765c378..aa8f248 100644
--- a/gcc/testsuite/g++.dg/modules/loc-prune-4.C
+++ b/gcc/testsuite/g++.dg/modules/loc-prune-4.C
@@ -18,5 +18,5 @@ int baz (int);
// { dg-final { scan-lang-dump {Ordinary maps:2 locs:12288 range_bits:5} module } }
// { dg-final { scan-lang-dump { 1 source file names\n Source file...=[^\n]*loc-prune-4.C\n} module } }
-// { dg-final { scan-lang-dump { Span:0 ordinary \[2.....\+12288,\+4096\)->\[0,\+4096\)} module } }
-// { dg-final { scan-lang-dump { Span:1 ordinary \[2.....\+40960,\+8192\)->\[4096,\+8192\)} module } }
+// { dg-final { scan-lang-dump { Span:0 ordinary \[[0-9]+\+12288,\+4096\)->\[0,\+4096\)} module } }
+// { dg-final { scan-lang-dump { Span:1 ordinary \[[0-9]+\+40960,\+8192\)->\[4096,\+8192\)} module } }
diff --git a/gcc/testsuite/g++.dg/no-stack-protector-attr-3.C b/gcc/testsuite/g++.dg/no-stack-protector-attr-3.C
index 76a5ec0..147c2b7 100644
--- a/gcc/testsuite/g++.dg/no-stack-protector-attr-3.C
+++ b/gcc/testsuite/g++.dg/no-stack-protector-attr-3.C
@@ -3,6 +3,7 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -fstack-protector-explicit" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-do compile { target { ! hppa*-*-* } } } */
diff --git a/gcc/testsuite/g++.dg/opt/pr94589-2.C b/gcc/testsuite/g++.dg/opt/pr94589-2.C
index 370deea..e9ef84b 100644
--- a/gcc/testsuite/g++.dg/opt/pr94589-2.C
+++ b/gcc/testsuite/g++.dg/opt/pr94589-2.C
@@ -1,7 +1,7 @@
// PR tree-optimization/94589
// { dg-do compile { target c++20 } }
// { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" }
-// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 12 "optimized" { xfail *-*-* } } }
+// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 12 "optimized" } }
// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 5\\.0" 12 "optimized" } }
#include <compare>
diff --git a/gcc/testsuite/g++.dg/pr104992-1.C b/gcc/testsuite/g++.dg/pr104992-1.C
index f5696b2..02b2882 100644
--- a/gcc/testsuite/g++.dg/pr104992-1.C
+++ b/gcc/testsuite/g++.dg/pr104992-1.C
@@ -1,6 +1,6 @@
/* PR tree-optimization/104992 */
/* { dg-do run } */
-/* { dg-options "-O2"} */
+/* { dg-options "-O2 -Wno-psabi" } */
#include "../gcc.dg/pr104992.c"
diff --git a/gcc/testsuite/g++.dg/pr71694.C b/gcc/testsuite/g++.dg/pr71694.C
index 5b59f87..60f246f 100644
--- a/gcc/testsuite/g++.dg/pr71694.C
+++ b/gcc/testsuite/g++.dg/pr71694.C
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fno-store-merging" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-fno-common -mdynamic-no-pic" { target { ia32 && { x86_64-*-darwin* i?86-*-darwin* } } } } */
struct B {
diff --git a/gcc/testsuite/g++.dg/stackprotectexplicit2.C b/gcc/testsuite/g++.dg/stackprotectexplicit2.C
index 35d9e88..70d8df4 100644
--- a/gcc/testsuite/g++.dg/stackprotectexplicit2.C
+++ b/gcc/testsuite/g++.dg/stackprotectexplicit2.C
@@ -2,6 +2,7 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -fstack-protector-explicit" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
int A()
{
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr101839.C b/gcc/testsuite/g++.dg/tree-ssa/pr101839.C
new file mode 100644
index 0000000..bb7b61c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr101839.C
@@ -0,0 +1,53 @@
+// { dg-do run }
+// { dg-options "-O2 -fdump-tree-optimized" }
+// { dg-require-effective-target c++11 }
+
+#include <string.h>
+#include <iostream>
+#include <map>
+namespace {
+ struct Buf {
+ char * buf; int a{0}; int b{0};
+ Buf(char * b) : buf(b) { }
+ void add(int v) {
+ ::memcpy(buf, &v, sizeof(v));
+ a += sizeof(v);
+ b += sizeof(v);
+ }
+ };
+ struct A {
+ virtual void fill(Buf &buf) {
+ buf.add(type());
+ buf.add(type());
+ }
+ virtual ~A() {}
+ virtual int type() = 0;
+ };
+ struct BA : A {
+ void fill(Buf &buf) {
+ A::fill(buf);
+ buf.add(type());
+ buf.add(type());
+ }
+ int type() final {
+ return 1;
+ }
+ };
+ struct CBA final : BA {
+ };
+ struct CA final : A {
+ ::std::map<int, int> m;
+ int type() final {
+ return 2;
+ }
+ };
+}
+int main(int argc, char ** ) {
+ char d[1024];
+ CBA cba;
+ Buf buf(d);
+ cba.fill(buf);
+ CA ca;
+ return 0;
+}
+// { dg-final { scan-tree-dump-not "__builtin_unreachable" "optimized" } }
diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
new file mode 100644
index 0000000..5152336
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O3 --save-temps" } */
+
+void foo (void)
+{
+ __bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} "" { xfail *-*-* } } */
+ __bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type '__bf16'} "" { xfail *-*-* } } */
+ __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} } */
+ __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/allocation-size-3.c b/gcc/testsuite/gcc.dg/analyzer/allocation-size-3.c
index 0c86f09..9590e31 100644
--- a/gcc/testsuite/gcc.dg/analyzer/allocation-size-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/allocation-size-3.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options -Wno-analyzer-out-of-bounds } */
+
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-4.c b/gcc/testsuite/gcc.dg/analyzer/fd-4.c
index 6b8fca5..842a26b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-4.c
@@ -1,3 +1,6 @@
+#ifdef _AIX
+#define _MODE_T
+#endif
#include <stdio.h>
int open(const char *, int mode);
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c b/gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c
index eba2570..b4f43e7 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-dup-1.c
@@ -220,4 +220,40 @@ test_19 (const char *path, void *buf)
close (fd);
}
-} \ No newline at end of file
+}
+
+extern int m;
+
+void
+test_20 ()
+{
+ int fd = dup (m);
+ close (fd);
+}
+
+void
+test_21 ()
+{
+ int fd = dup2 (m, 1);
+ close (fd);
+}
+
+void
+test_22 (int flags)
+{
+ int fd = dup3 (m, 1, flags);
+ close (fd);
+}
+
+void do_something();
+void
+test_23 ()
+{
+ int nullfd = -1;
+ int fd = 1;
+ if (dup2 (nullfd, fd) < 0) /* { dg-warning "'dup2' on possibly invalid file descriptor 'nullfd'" } */
+ {
+ do_something();
+ }
+}
+
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-uninit-1.c b/gcc/testsuite/gcc.dg/analyzer/fd-uninit-1.c
index b5b189e..1084d1b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-uninit-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-uninit-1.c
@@ -9,8 +9,6 @@ test_1 ()
{
int m;
return dup (m); /* { dg-warning "use of uninitialized value 'm'" "uninit" } */
- /* { dg-bogus "'dup' on possibly invalid file descriptor 'm'" "invalid fd false +ve" { xfail *-*-* } .-1 } */
- /* XFAIL: probably covered by fix for PR analyzer/106551. */
}
int
diff --git a/gcc/testsuite/gcc.dg/analyzer/memcpy-2.c b/gcc/testsuite/gcc.dg/analyzer/memcpy-2.c
index 88ec84c..51e4a69 100644
--- a/gcc/testsuite/gcc.dg/analyzer/memcpy-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/memcpy-2.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-Wno-stringop-overflow" } */
+/* { dg-additional-options "-Wno-stringop-overflow -Wno-analyzer-out-of-bounds" } */
void
main (int c, void *v)
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c
new file mode 100644
index 0000000..9f3cda6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c
@@ -0,0 +1,120 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+
+/* Wanalyzer-out-of-bounds tests for buffer overflows. */
+
+/* Avoid folding of memcpy. */
+typedef void * (*memcpy_t) (void *dst, const void *src, size_t n);
+
+static memcpy_t __attribute__((noinline))
+get_memcpy (void)
+{
+ return memcpy;
+}
+
+
+/* Taken from CWE-787. */
+void test1 (void)
+{
+ int id_sequence[3];
+
+ id_sequence[0] = 123;
+ id_sequence[1] = 234;
+ id_sequence[2] = 345;
+ id_sequence[3] = 456; /* { dg-line test1 } */
+
+ /* { dg-warning "overflow" "warning" { target *-*-* } test1 } */
+ /* { dg-message "" "note" { target *-*-* } test1 } */
+}
+
+void test2 (void)
+{
+ int n = 4;
+ int arr[4];
+
+ for (int i = n - 1; i >= 0; i--)
+ arr[i] = i;
+}
+
+void test3 (void)
+{
+ int n = 4;
+ int arr[4];
+
+ for (int i = n; i >= 0; i--)
+ arr[i] = i; /* { dg-line test3 } */
+
+ /* { dg-warning "overflow" "warning" { target *-*-* } test3 } */
+ /* { dg-message "" "note" { target *-*-* } test3 } */
+}
+
+void test4 (void)
+{
+ int *arr = malloc (4 * sizeof (int));
+ if (!arr)
+ return;
+
+ int *last_el = arr + 3;
+ *last_el = 3;
+
+ free (arr);
+}
+
+void test5 (void)
+{
+ int *arr = malloc (4 * sizeof (int));
+ if (!arr)
+ return;
+
+ int *last_el = arr + 4;
+ *last_el = 4; /* { dg-line test5 } */
+
+ free (arr);
+ /* { dg-warning "overflow" "warning" { target *-*-* } test5 } */
+ /* { dg-message "" "note" { target *-*-* } test5 } */
+}
+
+/* Taken from "A Provenance-aware Memory Object Model for C". */
+int y = 2, x = 1; /* { dg-message "capacity" } */
+void test6 (void)
+{
+ int *p = &x + 1;
+ int *q = &y;
+ printf ("Addresses: p=% p q=% p \n" , (void *) p, (void *) q);
+ if (memcmp (&p , &q , sizeof (p)) == 0)
+ {
+ *p = 11; /* { dg-line test6b } */
+ printf ("x=%d y=%d *p=%d *q=%d\n" , x, y, *p, *q); /* { dg-line test6c } */
+ }
+
+ /* { dg-warning "overflow" "warning" { target *-*-* } test6b } */
+ /* { dg-message "" "note" { target *-*-* } test6b } */
+ /* { dg-warning "overread" "warning" { target *-*-* } test6c } */
+ /* { dg-message "" "note" { target *-*-* } test6c } */
+}
+
+extern int is_valid (void);
+
+int returnChunkSize (void *ptr)
+{
+ /* If chunk info is valid, return the size of usable memory,
+ else, return -1 to indicate an error. */
+ return is_valid () ? sizeof (*ptr) : -1;
+}
+
+/* Taken from CWE-787. */
+void test7 (void)
+{
+ memcpy_t fn = get_memcpy ();
+
+ int destBuf[4];
+ int srcBuf[4];
+ fn (destBuf, srcBuf, returnChunkSize (destBuf)); /* { dg-line test7 } */
+
+ // TODO: Should we handle widening_svalues as a follow-up?
+ /* { dg-warning "overread" "warning" { xfail *-*-* } test7 } */
+ /* { dg-warning "overflow" "warning" { xfail *-*-* } test7 } */
+ /* { dg-message "" "note" { xfail *-*-* } test7 } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c
new file mode 100644
index 0000000..0df9364
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c
@@ -0,0 +1,83 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+
+/* Wanalyzer-out-of-bounds tests for buffer overreads. */
+
+/* Avoid folding of memcpy. */
+typedef void * (*memcpy_t) (void *dst, const void *src, size_t n);
+
+static memcpy_t __attribute__((noinline))
+get_memcpy (void)
+{
+ return memcpy;
+}
+
+
+void test1 (void)
+{
+ int id_sequence[3];
+ memset (id_sequence, 0, 3 * sizeof(int));
+ printf ("%i", id_sequence[3]); /* { dg-line test1 } */
+
+ /* { dg-warning "overread" "warning" { target *-*-* } test1 } */
+ /* { dg-message "" "note" { target *-*-* } test1 } */
+}
+
+void test2 (void)
+{
+ int n = 4;
+ int arr[n];
+ memset (arr, 0, n * sizeof (int));
+
+ int sum = 0;
+ for (int i = n - 1; i >= 0; i--)
+ sum += arr[i];
+}
+
+void test3 (void)
+{
+ int n = 4;
+ int arr[4];
+ memset (arr, 0, n * sizeof (int));
+
+ int sum = 0;
+ for (int i = n; i > 0; i--)
+ sum += arr[i]; /* { dg-line test3 } */
+
+ /* { dg-warning "overread" "warning" { target *-*-* } test3 } */
+ /* { dg-message "" "note" { target *-*-* } test3 } */
+}
+
+void test4 (void)
+{
+ int n = 4;
+ int *arr = malloc (n * sizeof (int));
+ if (!arr)
+ return;
+ memset (arr, 0, n * sizeof(int));
+
+ int sum = 0;
+ for (int i = n - 1; i >= 0; i--)
+ sum += *(arr + i);
+
+ free (arr);
+}
+
+void test5 (void)
+{
+ int n = 4;
+ int *arr = malloc (n * sizeof (int));
+ if (!arr)
+ return;
+ memset (arr, 0, n * sizeof(int));
+
+ int sum = 0;
+ for (int i = n; i > 0; i--)
+ sum += *(arr + i); /* { dg-line test5 } */
+
+ free (arr);
+ /* { dg-warning "overread" "warning" { target *-*-* } test5 } */
+ /* { dg-message "" "note" { target *-*-* } test5 } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c
new file mode 100644
index 0000000..7446b18
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c
@@ -0,0 +1,91 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+/* Wanalyzer-out-of-bounds tests for buffer underreads and writes. */
+
+/* Avoid folding of memcpy. */
+typedef void * (*memcpy_t) (void *dst, const void *src, size_t n);
+static memcpy_t __attribute__((noinline))
+get_memcpy (void)
+{
+ return memcpy;
+}
+
+
+void test1 (void)
+{
+ int buf[4];
+ int *e = buf - 1;
+ *e = 42; /* { dg-line test1 } */
+
+ /* { dg-warning "underflow" "warning" { target *-*-* } test1 } */
+ /* { dg-message "" "note" { target *-*-* } test1 } */
+}
+
+void test2 (void)
+{
+ int buf[4];
+ int *e = buf + 1;
+ *e = 123;
+ *(e - 1) = 321;
+}
+
+void test3 (void)
+{
+ int buf[4];
+ int *e = buf + 1;
+ *e = 123;
+ *(e - 2) = 321; /* { dg-line test3 } */
+
+ /* { dg-warning "underflow" "warning" { target *-*-* } test3 } */
+ /* { dg-message "" "note" { target *-*-* } test3 } */
+}
+
+void test4 (void)
+{
+ memcpy_t fn = get_memcpy ();
+ int buf[4];
+ memset (buf, 1, 4 * sizeof (int));
+ int n = -4;
+ fn (&(buf[n]), buf, sizeof (int)); /* { dg-line test4 } */
+
+ /* { dg-warning "underflow" "warning" { target *-*-* } test4 } */
+ /* { dg-message "" "note" { target *-*-* } test4 } */
+}
+
+void test5 (void)
+{
+ int buf[4];
+ memset (buf, 1, 4 * sizeof (int));
+
+ int sum = 0;
+ for (int i = 4; i >= 0; i++)
+ sum += *(buf - i); /* { dg-line test5 } */
+
+ /* { dg-warning "underread" "warning" { target *-*-* } test5 } */
+ /* { dg-message "" "note" { target *-*-* } test5 } */
+}
+
+void test6 (void)
+{
+ int buf[4];
+ memset (buf, 1, 4 * sizeof (int));
+
+ int *view = buf + 1;
+ int sum = 0;
+ for (int i = 0; i < 4; i++)
+ sum += *(view++);
+}
+
+void test8 (void)
+{
+ memcpy_t fn = get_memcpy ();
+ int buf[4];
+ memset (buf, 1, 4 * sizeof (int));
+ int n = -4;
+ fn (buf, &(buf[n]), sizeof (int)); /* { dg-line test8 } */
+
+ /* { dg-warning "underread" "warning" { target *-*-* } test8 } */
+ /* { dg-message "" "note" { target *-*-* } test8 } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c
new file mode 100644
index 0000000..172ec47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c
@@ -0,0 +1,51 @@
+/* Further reduced container_of pattern from the Linux Kernel. */
+
+struct inner {
+ /* Don't care */
+};
+
+struct outer {
+ int i;
+ struct inner inner_struct;
+};
+
+struct outer *container_of (struct inner *ptr_to_inner)
+{
+ struct outer *ptr_to_outer = ((struct outer *) (((void *) ptr_to_inner) - __builtin_offsetof(struct outer, inner_struct)));
+ return ptr_to_outer;
+}
+
+int test (struct outer *outer_p, struct inner *inner_p)
+{
+ struct outer test;
+ test.i = 42;
+ struct inner test2;
+ int sum = 0;
+ struct outer *o;
+
+ /* Symbolic inner struct. */
+ o = container_of (inner_p);
+ sum += o->i; // ok
+ /* Not ok, but we can't be sure that outer
+ is actually the container of inner. */
+ sum += (o - 1)->i;
+ /* Symbolic outer struct. */
+ o = container_of (&(outer_p->inner_struct));
+ sum += o->i; // ok
+ /* Not ok, but indistinguishable from the case above. */
+ sum += (o - 1)->i;
+ /* Concrete outer struct. */
+ o = container_of (&(test.inner_struct));
+ sum += o->i; // ok
+ /* Not ok and we do have a concrete region. */
+ sum += (o - 1)->i; /* { dg-line testA } */
+ /* Concrete inner struct, has no container. */
+ o = container_of (&test2);
+ sum += o->i; /* { dg-line testB } */
+
+ return sum;
+ /* { dg-warning "underread" "warning" { target *-*-* } testA } */
+ /* { dg-message "" "note" { target *-*-* } testA } */
+ /* { dg-warning "underread" "warning" { target *-*-* } testB } */
+ /* { dg-message "" "note" { target *-*-* } testB } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-coreutils.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-coreutils.c
new file mode 100644
index 0000000..cd0f4b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-coreutils.c
@@ -0,0 +1,29 @@
+/* Reduced from coreutils/ls.c attach. */
+
+void add_zero_terminator (char *buf)
+{
+ char *end = buf;
+ while (end++);
+ if (buf < end)
+ end[-1] = '\0';
+}
+
+/* Reduced from coreutils/cat.c. */
+
+#define LINE_COUNTER_BUF_LEN 20
+static char line_buf[LINE_COUNTER_BUF_LEN] =
+ {
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0',
+ '\t', '\0'
+ };
+
+/* Position of the first digit in 'line_buf'. */
+static char *line_num_start = line_buf + LINE_COUNTER_BUF_LEN - 3;
+
+static void
+next_line_num (void)
+{
+ if (line_num_start > line_buf)
+ *--line_num_start = '1';
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c
new file mode 100644
index 0000000..e34b572
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c
@@ -0,0 +1,41 @@
+/* { dg-additional-options "-O2" } */
+#include <string.h>
+
+/* Reduced from curl lib/smb.c. */
+typedef int CURLcode;
+
+struct smb_conn {
+ // [...]
+ char *user;
+};
+
+struct smb_setup {
+ // [...]
+ char bytes[48];
+} __attribute__((packed));
+
+struct connectdata {
+ // [...]
+ struct smb_conn *smbc;
+};
+
+CURLcode smb_send_setup (struct connectdata *conn)
+{
+ struct smb_conn *smbc = conn->smbc;
+ struct smb_setup msg;
+ char *p = msg.bytes;
+ unsigned char lm[24];
+
+ /* Init to prevent uninit warning. */
+ memset(&msg, 0, sizeof(msg));
+ memset (&lm, 0, sizeof(lm));
+
+ memcpy(p, lm, sizeof(lm));
+ p += sizeof(lm);
+ /* Had a false-positive overflow at p. Checker had a number of bytes copied
+ relative to the start but offset points in the middle the field. */
+ strcpy(p, (smbc->user));
+ p += strlen(smbc->user) + 1;
+
+ return 1;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c
new file mode 100644
index 0000000..61cbfc7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c
@@ -0,0 +1,55 @@
+char arr[10]; /* { dg-message "capacity is 10 bytes" } */
+
+char int_arr_read_element_before_start_far(void)
+{
+ return arr[-100]; /* { dg-warning "buffer underread" "warning" } */
+ /* { dg-message "out-of-bounds read at byte -100 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+char int_arr_read_element_before_start_near(void)
+{
+ return arr[-2]; /* { dg-warning "buffer underread" "warning" } */
+ /* { dg-message "out-of-bounds read at byte -2 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+char int_arr_read_element_before_start_off_by_one(void)
+{
+ return arr[-1]; /* { dg-warning "buffer underread" "warning" } */
+ /* { dg-message "out-of-bounds read at byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+char int_arr_read_element_at_start(void)
+{
+ return arr[0];
+}
+
+char int_arr_read_element_at_end(void)
+{
+ return arr[9];
+}
+
+char int_arr_read_element_after_end_off_by_one(void)
+{
+ return arr[10]; /* { dg-warning "buffer overread" "warning" } */
+ /* { dg-message "out-of-bounds read at byte 10 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "read is 1 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): "1 bytes"
+}
+
+char int_arr_read_element_after_end_near(void)
+{
+ return arr[11]; /* { dg-warning "buffer overread" "warning" } */
+ /* { dg-message "out-of-bounds read at byte 11 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "read is 1 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): is the note correct?
+ // FIXME(PR 106626): "1 bytes"
+}
+
+char int_arr_read_element_after_end_far(void)
+{
+ return arr[100]; /* { dg-warning "buffer overread" "warning" } */
+ /* { dg-message "out-of-bounds read at byte 100 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "read is 1 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): the note seems incorrect (size of access is 1 byte, but magnitude beyond boundary is 90)
+ // FIXME(PR 106626): "1 bytes"
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c
new file mode 100644
index 0000000..0bb30d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c
@@ -0,0 +1,54 @@
+#include <stdint.h>
+
+int32_t arr[10]; /* { dg-message "capacity is 40 bytes" } */
+
+int32_t int_arr_read_element_before_start_far(void)
+{
+ return arr[-100]; /* { dg-warning "buffer underread" "warning" } */
+ /* { dg-message "out-of-bounds read from byte -400 till byte -397 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+int32_t int_arr_read_element_before_start_near(void)
+{
+ return arr[-2]; /* { dg-warning "buffer underread" "warning" } */
+ /* { dg-message "out-of-bounds read from byte -8 till byte -5 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+int32_t int_arr_read_element_before_start_off_by_one(void)
+{
+ return arr[-1]; /* { dg-warning "buffer underread" "warning" } */
+ /* { dg-message "out-of-bounds read from byte -4 till byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+int32_t int_arr_read_element_at_start(void)
+{
+ return arr[0];
+}
+
+int32_t int_arr_read_element_at_end(void)
+{
+ return arr[9];
+}
+
+int32_t int_arr_read_element_after_end_off_by_one(void)
+{
+ return arr[10]; /* { dg-warning "buffer overread" "warning" } */
+ /* { dg-message "out-of-bounds read from byte 40 till byte 43 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "read is 4 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+}
+
+int32_t int_arr_read_element_after_end_near(void)
+{
+ return arr[11]; /* { dg-warning "buffer overread" "warning" } */
+ /* { dg-message "out-of-bounds read from byte 44 till byte 47 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "read is 4 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): is the note correct?
+}
+
+int32_t int_arr_read_element_after_end_far(void)
+{
+ return arr[100]; /* { dg-warning "buffer overread" "warning" } */
+ /* { dg-message "out-of-bounds read from byte 400 till byte 403 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "read is 4 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): the note seems incorrect (size of access is 4 bytes, but magnitude beyond boundary is 390-393)
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c
new file mode 100644
index 0000000..47fbc52
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c
@@ -0,0 +1,55 @@
+char arr[10]; /* { dg-message "capacity is 10 bytes" } */
+
+void int_arr_write_element_before_start_far(char x)
+{
+ arr[-100] = x; /* { dg-warning "buffer underflow" "warning" } */
+ /* { dg-message "out-of-bounds write at byte -100 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+void int_arr_write_element_before_start_near(char x)
+{
+ arr[-2] = x; /* { dg-warning "buffer underflow" "warning" } */
+ /* { dg-message "out-of-bounds write at byte -2 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+void int_arr_write_element_before_start_off_by_one(char x)
+{
+ arr[-1] = x; /* { dg-warning "buffer underflow" "warning" } */
+ /* { dg-message "out-of-bounds write at byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+void int_arr_write_element_at_start(char x)
+{
+ arr[0] = x;
+}
+
+void int_arr_write_element_at_end(char x)
+{
+ arr[9] = x;
+}
+
+void int_arr_write_element_after_end_off_by_one(char x)
+{
+ arr[10] = x; /* { dg-warning "buffer overflow" "warning" } */
+ /* { dg-message "out-of-bounds write at byte 10 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "write is 1 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): "1 bytes"
+}
+
+void int_arr_write_element_after_end_near(char x)
+{
+ arr[11] = x; /* { dg-warning "buffer overflow" "warning" } */
+ /* { dg-message "out-of-bounds write at byte 11 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "write is 1 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): is the note correct?
+ // FIXME(PR 106626): "1 bytes"
+}
+
+void int_arr_write_element_after_end_far(char x)
+{
+ arr[100] = x; /* { dg-warning "buffer overflow" "warning" } */
+ /* { dg-message "out-of-bounds write at byte 100 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "write is 1 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): the note seems incorrect (size of access is 1 byte, but magnitude beyond boundary is 90)
+ // FIXME(PR 106626): "1 bytes"
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c
new file mode 100644
index 0000000..bf9760e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c
@@ -0,0 +1,54 @@
+#include <stdint.h>
+
+int32_t arr[10]; /* { dg-message "capacity is 40 bytes" } */
+
+void int_arr_write_element_before_start_far(int32_t x)
+{
+ arr[-100] = x; /* { dg-warning "buffer underflow" "warning" } */
+ /* { dg-message "out-of-bounds write from byte -400 till byte -397 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+void int_arr_write_element_before_start_near(int32_t x)
+{
+ arr[-2] = x; /* { dg-warning "buffer underflow" "warning" } */
+ /* { dg-message "out-of-bounds write from byte -8 till byte -5 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+void int_arr_write_element_before_start_off_by_one(int32_t x)
+{
+ arr[-1] = x; /* { dg-warning "buffer underflow" "warning" } */
+ /* { dg-message "out-of-bounds write from byte -4 till byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+}
+
+void int_arr_write_element_at_start(int32_t x)
+{
+ arr[0] = x;
+}
+
+void int_arr_write_element_at_end(int32_t x)
+{
+ arr[9] = x;
+}
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-warning "buffer overflow" "warning" } */
+ /* { dg-message "out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "write is 4 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+}
+
+void int_arr_write_element_after_end_near(int32_t x)
+{
+ arr[11] = x; /* { dg-warning "buffer overflow" "warning" } */
+ /* { dg-message "out-of-bounds write from byte 44 till byte 47 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "write is 4 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): is the note correct?
+}
+
+void int_arr_write_element_after_end_far(int32_t x)
+{
+ arr[100] = x; /* { dg-warning "buffer overflow" "warning" } */
+ /* { dg-message "out-of-bounds write from byte 400 till byte 403 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "write is 4 bytes past the end of 'arr'" "note" { target *-*-* } .-2 } */
+ // FIXME(PR 106626): the note seems incorrect (size of access is 4 bytes, but magnitude beyond boundary is 390-393)
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101962.c b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
index d15820a..cf0041b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr101962.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
@@ -22,8 +22,10 @@ test_1 (void)
a = maybe_inc_int_ptr (a);
__analyzer_eval (a == NULL); /* { dg-warning "FALSE" } */
__analyzer_eval (a != NULL); /* { dg-warning "TRUE" } */
- return *a; /* { dg-warning "use of uninitialized value '\\*a'" } */
- /* TODO: a complaint about out-of-bounds would be a better warning. */
+ return *a; /* { dg-line test_1 } */
+
+ /* { dg-warning "use of uninitialized value '\\*a'" "warning" { target *-*-* } test_1 } */
+ /* { dg-warning "overread" "warning" { target *-*-* } test_1 } */
}
static const char * __attribute__((noinline))
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr106539.c b/gcc/testsuite/gcc.dg/analyzer/pr106539.c
new file mode 100644
index 0000000..fd27086
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr106539.c
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+
+void *test (void)
+{
+ void **p = (void **)malloc (sizeof (void *) * 2);
+ if (!p)
+ return NULL;
+ p[0] = malloc(10);
+ p[1] = malloc(20); /* { dg-message "allocated here" } */
+ void *q = realloc (p, sizeof (void *)); /* { dg-message "when 'realloc' succeeds, moving buffer" } */
+ if (!q)
+ /* { dg-warning "leak of '<unknown>'" "leak of unknown" { target *-*-* } .-1 } */
+ return p;
+ return q;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96764.c b/gcc/testsuite/gcc.dg/analyzer/pr96764.c
index 70b25d3..6024eba 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr96764.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr96764.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-out-of-bounds" } */
+
void
ar (int *hd)
{
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr97029.c b/gcc/testsuite/gcc.dg/analyzer/pr97029.c
index ff83ad4..e3b4531 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr97029.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr97029.c
@@ -1,4 +1,6 @@
-struct vj {};
+struct vj {
+ char buf[1];
+};
void
setjmp (struct vj pl)
diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-5.c b/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
new file mode 100644
index 0000000..2efe337
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
@@ -0,0 +1,45 @@
+#include "analyzer-decls.h"
+
+typedef __SIZE_TYPE__ size_t;
+
+#define NULL ((void *)0)
+
+extern void *malloc (size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__malloc__))
+ __attribute__ ((__alloc_size__ (1)));
+extern void *realloc (void *__ptr, size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__warn_unused_result__))
+ __attribute__ ((__alloc_size__ (2)));
+extern void free (void *__ptr)
+ __attribute__ ((__nothrow__ , __leaf__));
+extern void *memset (void *__ptr, int __value, size_t __size);
+
+/* realloc where the region shrinks on success_with_move. */
+
+void test_1 ()
+{
+ char *p = malloc (16);
+ if (!p)
+ return;
+ memset (p, 1, 16);
+
+ char *q = realloc (p, 8);
+ if (!q)
+ {
+ free (p);
+ return;
+ }
+ else if (p != q)
+ {
+ __analyzer_dump_capacity (q); /* { dg-warning "capacity: '\\(\[^\n\r\]*\\)8'" } */
+ __analyzer_eval (q[8] == 1); /* { dg-line eval } */
+
+ /* { dg-warning "UNKNOWN" "warning" { target *-*-* } eval } */
+ /* { dg-warning "overread" "warning" { target *-*-* } eval } */
+ /* { dg-warning "use of uninitialized value" "warning" { target *-*-* } eval } */
+ }
+
+ free (q);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/test-setjmp.h b/gcc/testsuite/gcc.dg/analyzer/test-setjmp.h
index db24227..52c57d0 100644
--- a/gcc/testsuite/gcc.dg/analyzer/test-setjmp.h
+++ b/gcc/testsuite/gcc.dg/analyzer/test-setjmp.h
@@ -12,7 +12,9 @@
#pragma GCC system_header
-struct __jmp_buf_tag {};
+struct __jmp_buf_tag {
+ char buf[1];
+};
typedef struct __jmp_buf_tag jmp_buf[1];
typedef struct __jmp_buf_tag sigjmp_buf[1];
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr93451.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr93451.c
index 5908bc4..daac745 100644
--- a/gcc/testsuite/gcc.dg/analyzer/torture/pr93451.c
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr93451.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-out-of-bounds" } */
+
void
mt (double);
diff --git a/gcc/testsuite/gcc.dg/analyzer/zlib-3.c b/gcc/testsuite/gcc.dg/analyzer/zlib-3.c
index 5098b4f..b05b862 100644
--- a/gcc/testsuite/gcc.dg/analyzer/zlib-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/zlib-3.c
@@ -182,7 +182,9 @@ static int huft_build(uInt *b, uInt n, uInt s, const uInt *d, const uInt *e,
q[j] = r; /* { dg-warning "use of uninitialized value 'r.base'" } */
mask = (1 << w) - 1;
- while ((i & mask) != x[h]) {
+ /* The analyzer thinks that h can be -1 here.
+ This is probably a false positive. */
+ while ((i & mask) != x[h]) { /* { dg-bogus "underread" "" { xfail *-*-* } } */
h--;
w -= l;
mask = (1 << w) - 1;
diff --git a/gcc/testsuite/gcc.dg/pr102892-1.c b/gcc/testsuite/gcc.dg/pr102892-1.c
index a9302b5..f08b2b8 100644
--- a/gcc/testsuite/gcc.dg/pr102892-1.c
+++ b/gcc/testsuite/gcc.dg/pr102892-1.c
@@ -1,5 +1,6 @@
/* { dg-do link } */
/* { dg-options "-O3" } */
+/* { dg-additional-options "-fno-PIC" { target ia32 } } */
/* { dg-additional-sources "pr102892-2.c" } */
static long b[2][1] = {0};
diff --git a/gcc/testsuite/gcc.dg/pr104992.c b/gcc/testsuite/gcc.dg/pr104992.c
index b9d91a1..217c89a 100644
--- a/gcc/testsuite/gcc.dg/pr104992.c
+++ b/gcc/testsuite/gcc.dg/pr104992.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/104992 */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -Wno-psabi -fdump-tree-optimized" } */
#define vector __attribute__((vector_size(4*sizeof(int))))
diff --git a/gcc/testsuite/gcc.dg/pr106243-1.c b/gcc/testsuite/gcc.dg/pr106243-1.c
index b1dbe5c..cb3b74c 100644
--- a/gcc/testsuite/gcc.dg/pr106243-1.c
+++ b/gcc/testsuite/gcc.dg/pr106243-1.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/106243 */
/* { dg-do run } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -Wno-psabi" } */
#include "pr106243.c"
diff --git a/gcc/testsuite/gcc.dg/pr106243.c b/gcc/testsuite/gcc.dg/pr106243.c
index ee2706f..8a7e0bf 100644
--- a/gcc/testsuite/gcc.dg/pr106243.c
+++ b/gcc/testsuite/gcc.dg/pr106243.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/106243 */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -Wno-psabi -fdump-tree-optimized" } */
#define vector __attribute__((vector_size(4*sizeof(int))))
diff --git a/gcc/testsuite/gcc.dg/pr106621.c b/gcc/testsuite/gcc.dg/pr106621.c
new file mode 100644
index 0000000..0465de4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr106621.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target aarch64*-*-* } } */
+/* { dg-options "-mcpu=neoverse-v1 -O2 -fvect-cost-model=dynamic -fno-tree-scev-cprop" } */
+
+int m, n;
+
+void
+foo (unsigned int x, short int y)
+{
+ if (m)
+ for (;;)
+ {
+ ++m;
+ while (m < 1)
+ {
+ n += m + x;
+ ++m;
+ }
+ }
+
+ for (;;)
+ if (y)
+ {
+ ++x;
+ if (x)
+ for (y = 0; y < 75; y += 2)
+ {
+ }
+ }
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr64992.c b/gcc/testsuite/gcc.dg/pr64992.c
new file mode 100644
index 0000000..43fbcf7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64992.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+_Bool foo(_Bool x) { return (x << 2) != 0; }
+_Bool bar(_Bool x) { return (x << 2) == 0; }
+
+/* { dg-final { scan-tree-dump-not " << " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr71343-1.c b/gcc/testsuite/gcc.dg/pr71343-1.c
new file mode 100644
index 0000000..146f5fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr71343-1.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+unsigned int foo_plus(unsigned int a, unsigned int b)
+{
+ return (a << 2) + (b << 2);
+}
+
+unsigned int foo_and(unsigned int a, unsigned int b)
+{
+ return (a << 2) & (b << 2);
+}
+
+unsigned int foo_ior(unsigned int a, unsigned int b)
+{
+ return (a << 2) | (b << 2);
+}
+
+unsigned int foo_xor(unsigned int a, unsigned int b)
+{
+ return (a << 2) ^ (b << 2);
+}
+
+unsigned int bar_and(unsigned int a, unsigned int b)
+{
+ return (a >> 2) & (b >> 2);
+}
+
+unsigned int bar_ior(unsigned int a, unsigned int b)
+{
+ return (a >> 2) | (b >> 2);
+}
+
+unsigned int bar_xor(unsigned int a, unsigned int b)
+{
+ return (a >> 2) ^ (b >> 2);
+}
+
+int baz_and(int a, int b)
+{
+ return (a >> 2) & (b >> 2);
+}
+
+int baz_ior(int a, int b)
+{
+ return (a >> 2) | (b >> 2);
+}
+
+int baz_xor(int a, int b)
+{
+ return (a >> 2) ^ (b >> 2);
+}
+
+/* { dg-final { scan-tree-dump-times " << " 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " >> " 6 "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/sibcall-11.c b/gcc/testsuite/gcc.dg/sibcall-11.c
index ae58770..12f6d9c9 100644
--- a/gcc/testsuite/gcc.dg/sibcall-11.c
+++ b/gcc/testsuite/gcc.dg/sibcall-11.c
@@ -1,5 +1,6 @@
// Test for sibcall optimization with empty struct.
// { dg-options "-O2" }
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
// { dg-final { scan-assembler "jmp" { target i?86-*-* x86_64-*-* } } }
struct A { };
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-self.c b/gcc/testsuite/gcc.dg/torture/builtin-self.c
index 6d1719f..56188fc 100644
--- a/gcc/testsuite/gcc.dg/torture/builtin-self.c
+++ b/gcc/testsuite/gcc.dg/torture/builtin-self.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* Check that we can use this idiom to define out-of-line copies of built-in
functions. This is used by libgcc/sync.c, for example. */
void __sync_synchronize (void)
diff --git a/gcc/testsuite/gcc.dg/torture/pr106513.c b/gcc/testsuite/gcc.dg/torture/pr106513.c
new file mode 100644
index 0000000..aa4f4d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr106513.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+
+typedef __INT64_TYPE__ int64_t;
+
+__attribute__((noinline)) int64_t
+swap64 (int64_t n)
+{
+ return (((n & (((int64_t) 0xff) )) << 56) |
+ ((n & (((int64_t) 0xff) << 8)) << 40) |
+ ((n & (((int64_t) 0xff) << 16)) << 24) |
+ ((n & (((int64_t) 0xff) << 24)) << 8) |
+ ((n & (((int64_t) 0xff) << 32)) >> 8) |
+ ((n & (((int64_t) 0xff) << 40)) >> 24) |
+ ((n & (((int64_t) 0xff) << 48)) >> 40) |
+ ((n & ((int64_t)(0xffull << 56))) >> 56));
+}
+
+int main (void)
+{
+ volatile int64_t n = 0x8000000000000000ll;
+
+ if (swap64(n) != 0xffffffffffffff80ll)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr106590.c b/gcc/testsuite/gcc.dg/torture/pr106590.c
new file mode 100644
index 0000000..b7b8472
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr106590.c
@@ -0,0 +1,75 @@
+/* PR rtl-optimization/106590 } */
+/* { dg-do run } */
+/* { dg-additional-options "-mtune=skylake" { target { i?86-*-* x86_64-*-* } } } */
+
+typedef struct A { short a; } A;
+typedef A *B;
+typedef struct C { int c, d; } C;
+typedef C *D;
+
+B
+foo (void)
+{
+ static A r = { .a = 1 };
+ return &r;
+}
+
+D
+bar (void)
+{
+ static C r = { .c = 1, .d = 23 };
+ return &r;
+}
+
+static inline int __attribute__((always_inline))
+baz (short a)
+{
+ int e = 1, f;
+ short g;
+ D h;
+
+ switch (a)
+ {
+ case 1:
+ f = 23;
+ g = 1;
+ break;
+ case 2:
+ f = 20;
+ g = 2;
+ break;
+ }
+
+ h = bar ();
+
+ if (h->d != f || h->c != g)
+ __builtin_abort ();
+ return e;
+}
+
+int
+qux (void)
+{
+ B i = foo ();
+ int e = 1;
+
+ switch (i->a)
+ {
+ case 1:
+ case 2:
+ e = baz (i->a);
+ break;
+ case 3:
+ e = 0;
+ break;
+ }
+
+ return e;
+}
+
+int
+main ()
+{
+ qux ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-18.c
new file mode 100644
index 0000000..a899f4f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-18.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-threadfull1-stats" } */
+
+void foo (int nest, int print_nest)
+{
+ _Bool t0 = nest != 0;
+ _Bool t1 = nest == print_nest;
+ _Bool t2 = t0 & t1;
+ if (t2)
+ __builtin_puts ("x");
+ nest++;
+ if (nest > 2)
+ __builtin_abort ();
+ if (print_nest == nest)
+ __builtin_puts ("y");
+}
+
+/* We should be able to thread (t2) to !(print_nest == nest) using the
+ nest == print_nest relation implied by the entry block. */
+/* { dg-final { scan-tree-dump "Jumps threaded: 1" "threadfull1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-19.c
new file mode 100644
index 0000000..62912f3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-19.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-threadfull1-stats" } */
+
+struct S;
+struct S { struct S *next; };
+int foo (struct S *chain, _Bool is_ctor, _Bool is_dtor)
+{
+ int num_args = 0;
+ if (chain) /* A */
+ {
+ do {
+ num_args++;
+ chain = chain->next;
+ if (!chain)
+ break;
+ } while (1);
+ }
+ if (is_ctor)
+ num_args++; /* B */
+ if (is_dtor)
+ num_args++;
+ else
+ {
+ if (num_args > 2) /* C */
+ __builtin_puts ("x");
+ }
+ return num_args;
+}
+
+/* We want to thread both paths from A with NULL chain to C, the one through
+ B and one around it.
+ ??? Ideally we'd thread one "path" containing the half-diamond with B. */
+/* { dg-final { scan-tree-dump "Jumps threaded: 2" "threadfull1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-20.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-20.c
new file mode 100644
index 0000000..c652965
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-20.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ethread-stats" } */
+
+struct S { int base; };
+void foo (struct S *p)
+{
+ if (p)
+ {
+ int *q = &p->base;
+ if (q)
+ __builtin_puts ("x");
+ }
+}
+
+/* { dg-final { scan-tree-dump "Jumps threaded: 1" "ethread" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr106524.c b/gcc/testsuite/gcc.target/aarch64/sve/pr106524.c
new file mode 100644
index 0000000..a9f650f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr106524.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+sve -O2 -fno-move-loop-invariants" } */
+
+void
+test__zero (int *restrict dest, int *restrict src, float *a, int count)
+{
+ int i;
+
+ for (i = 0; i < count; ++i)
+ dest[i] = !__builtin_isunordered (a[i], 0) ? src[i] : 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-dest-false-dep-for-glc.c b/gcc/testsuite/gcc.target/i386/avx2-dest-false-dep-for-glc.c
index 787b1d0..fe331fe 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-dest-false-dep-for-glc.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-dest-false-dep-for-glc.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -mtune=generic -mtune-ctrl=dest_false_dep_for_glc -O2" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c b/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c
index bf29a69..831abd3 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bf16-cvtsbh2ss-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bf16 -O2" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-times "sall\[ \\t\]+\[^\{\n\]*16" 1 } } */
/* { dg-final { scan-assembler-times "movl" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c
index a2664d8..0fa93e0 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-1.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f -mavx512dq" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 2 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 5 { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-3.c b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-3.c
index e57a568..b1a75f2 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-3.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 4 } } */
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to16\\\}" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c
index 477f9ca..f1b672a 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-5.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 4 { target ia32 } } } */
/* { dg-final { scan-assembler-times "vpbroadcastd\[\\t \]+%(?:r|e)\[^\n\]*, %zmm\[0-9\]+" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-7.c b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-7.c
index 194d888..1f141d0 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-7.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-broadcast-pr87767-7.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f -mavx512vl" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "vadd\[^\n\]*\\\{1to2\\\}" 1 } } */
/* { dg-final { scan-assembler-times "vadd\[^\n\]*\\\{1to4\\\}" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c b/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c
index 3e2397f..1e9b8f3 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-broadcast-1.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512fp16 -mavx512vl -mavx512dq" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to8\\\}" 4 } } */
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to16\\\}" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c b/gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c
index abd9156..01571d2 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-pr101846.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -mavx512vl -O2" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-times "vpmovzxwd" "3" } } */
/* { dg-final { scan-assembler-times "vpmovdw" "3" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c
index f29c953..7200f29 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2si-1a.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
-/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2si\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c
index 7d00867..0d00803 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvtsh2usi-1a.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
-/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
+/* { dg-final { scan-assembler-times "vcvtsh2usi\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c
index 80d84fc..4fb0684 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2si-1a.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
-/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2si\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c
index 5956457..3d408f1 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vcvttsh2usi-1a.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
-/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%eax" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
+/* { dg-final { scan-assembler-times "vcvttsh2usi\[ \\t\]+\{sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%e\[ad]x" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c
index e35be10..ba10096 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vmovsh-1a.c
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r\]*%\[er\]ax+\[^\n\r]*\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+\[^\n\r\]*%\[er\]ax+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+\[^\n\r\]*%\[er\]ax+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r\]*%\[er\]\[ad]x+\[^\n\r]*\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+\[^\n\r\]*%\[er\]\[ad]x+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+\[^\n\r\]*%\[er\]\[ad]x+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^z\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vmovsh\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c
index f8eb99f..0304b9d 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-1.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f -mavx512vl -mavx512dq" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 2 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 4 { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-3.c b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-3.c
index 3b27def..8ad8fd7 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-3.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f -mavx512vl" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 4 } } */
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c
index 32f6ac8..0ba0cd9 100644
--- a/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-broadcast-pr87767-5.c
@@ -1,6 +1,7 @@
/* PR target/87767 */
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512f -mavx512vl" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } }
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to2\\\}" 4 { target ia32 } } } */
/* { dg-final { scan-assembler-times "\[^\n\]*\\\{1to4\\\}" 4 { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/bfloat16-1.c b/gcc/testsuite/gcc.target/i386/bfloat16-1.c
new file mode 100644
index 0000000..6aaec28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/bfloat16-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+__bf16
+foo (int a)
+{
+ union {
+ int a;
+ __bf16 b;
+ }c;
+ c.a = a;
+ return c.b;
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c
index c3d0eb9..6cc88ad 100644
--- a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c
@@ -2,10 +2,8 @@
/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O -maddress-mode=short -fcf-protection -mx32" } */
/* { dg-final { scan-assembler-times "endbr64" 2 } } */
-/* { dg-final { scan-assembler-times "movq\t\[^\n\]*buf\\+8" 1 { target nonpic } } } */
-/* { dg-final { scan-assembler-times "movq\t\[^\n\]*8\\+buf" 1 { target { ! nonpic } } } } */
-/* { dg-final { scan-assembler-times "subq\tbuf\\+8" 1 { target nonpic } } } */
-/* { dg-final { scan-assembler-times "subq\t8\\+buf" 1 { target { ! nonpic } } } } */
+/* { dg-final { scan-assembler-times "movq\t\[^\n\]*(?:8\\+buf|buf\\+8)" 1 } } */
+/* { dg-final { scan-assembler-times "subq\t(?:8\\+buf|buf\\+8)" 1 } } */
/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */
/* { dg-final { scan-assembler-times "rdsspq" 2 } } */
/* { dg-final { scan-assembler-times "incsspq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
index 4c52685..b80acfd 100644
--- a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
@@ -2,10 +2,8 @@
/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O -maddress-mode=long -fcf-protection -mx32" } */
/* { dg-final { scan-assembler-times "endbr64" 2 } } */
-/* { dg-final { scan-assembler-times "movq\t\[^\n\]*buf\\+16" 1 { target nonpic } } } */
-/* { dg-final { scan-assembler-times "movq\t\[^\n\]*16\\+buf" 1 { target { ! nonpic } } } } */
-/* { dg-final { scan-assembler-times "subq\tbuf\\+16" 1 { target nonpic } } } */
-/* { dg-final { scan-assembler-times "subq\t16\\+buf" 1 { target { ! nonpic } } } } */
+/* { dg-final { scan-assembler-times "movq\t\[^\n\]*(?:16\\+buf|buf\\+16)" 1 } } */
+/* { dg-final { scan-assembler-times "subq\t(?:16\\+buf|buf\\+16)" 1 } } */
/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */
/* { dg-final { scan-assembler-times "rdsspq" 2 } } */
/* { dg-final { scan-assembler-times "incsspq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-11.c b/gcc/testsuite/gcc.target/i386/interrupt-11.c
index ded589e..4a119b9 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-11.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-11.c
@@ -15,7 +15,7 @@ foo (void *frame)
/* { dg-final { scan-assembler-not "kmov.\[\\t \]*\[0-9\]*\\(%\[re\]?sp\\),\[\\t \]*%k\[0-7\]+" } } */
/* { dg-final { scan-assembler-not "pushq\[\\t \]*%rbx" { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-not "pushq\[\\t \]*%r1\[2-5\]+" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "pushl\[\\t \]*%ebx" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "pushl\[\\t \]*%ebx" { target { ia32 && nonpic } } } } */
/* { dg-final { scan-assembler-not "pushl\[\\t \]*%edi" { target ia32 } } } */
/* { dg-final { scan-assembler-not "pushl\[\\t \]*%esi" { target ia32 } } } */
/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)ax" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-12.c b/gcc/testsuite/gcc.target/i386/interrupt-12.c
index 078bbcf..4e91a27 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-12.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-12.c
@@ -12,7 +12,8 @@ fn1 (void *frame, uword_t error)
}
/* { dg-final { scan-assembler-not "movups\[\\t .\]*%(x|y|z)mm\[0-9\]+" } } */
-/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(b|c|d)x" } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)bx" { target { nonpic || { ! ia32 } } } } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(c|d)x" } } */
/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)si" } } */
/* { dg-final { scan-assembler-not "(push|pop)l\[\\t \]*%edi" { target ia32 } } } */
/* { dg-final { scan-assembler-not "(push|pop)q\[\\t \]*%rax" { target { { ! ia32 } && nonpic } } } } */
@@ -20,7 +21,8 @@ fn1 (void *frame, uword_t error)
/* { dg-final { scan-assembler-times "pushl\[\\t \]*%ebp" 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "leave" 1 { target { ia32 && nonpic } } } } */
/* { dg-final { scan-assembler-times "pushl\[\\t \]*%eax" 1 { target ia32 } } } */
-/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%eax" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%eax" 1 { target { ia32 && nonpic } } } } */
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%eax" 1 { target { ia32 && { ! nonpic } } } } } */
/* { dg-final { scan-assembler-times "pushq\[\\t \]*%rdi" 1 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "popq\[\\t \]*%rdi" 1 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler "(addl|leal).*4.*%esp" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-13.c b/gcc/testsuite/gcc.target/i386/interrupt-13.c
index 77ee3a5..4afd1b0 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-13.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-13.c
@@ -12,7 +12,8 @@ fn1 (void *frame, uword_t error)
}
/* { dg-final { scan-assembler-not "movups\[\\t .\]*%(x|y|z)mm\[0-9\]+" } } */
-/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(b|c|d)x" } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)bx" { target { nonpic || { ! ia32 } } } } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(c|d)x" } } */
/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)si" } } */
/* { dg-final { scan-assembler-not "(push|pop)l\[\\t \]*%edi" { target ia32 } } } */
/* { dg-final { scan-assembler-not "(push|pop)q\[\\t \]*%rax" { target { { ! ia32 } && nonpic } } } } */
@@ -20,7 +21,8 @@ fn1 (void *frame, uword_t error)
/* { dg-final { scan-assembler-times "pushl\[\\t \]*%ebp" 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "leave" 1 { target { ia32 && nonpic } } } } */
/* { dg-final { scan-assembler-times "pushl\[\\t \]*%eax" 1 { target ia32 } } } */
-/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%eax" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%eax" 1 { target { ia32 && nonpic } } } } */
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%eax" 1 { target { ia32 && { ! nonpic } } } } } */
/* { dg-final { scan-assembler-times "pushq\[\\t \]*%rdi" 1 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "popq\[\\t \]*%rdi" 1 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler "(addl|leal).*4.*%esp" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-15.c b/gcc/testsuite/gcc.target/i386/interrupt-15.c
index 2a0d260..f43aabc 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-15.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-15.c
@@ -19,7 +19,8 @@ fn2 (void *frame, uword_t error)
}
/* { dg-final { scan-assembler-not "movups\[\\t .\]*%(x|y|z)mm\[0-9\]+" } } */
-/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(b|c|d)x" } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)ax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(c|d)x" } } */
/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)si" } } */
/* { dg-final { scan-assembler-not "(push|pop)l\[\\t \]*%edi" { target ia32 } } } */
/* { dg-final { scan-assembler-not "(push|pop)q\[\\t \]*%rax" { target { { ! ia32 } && nonpic } } } } */
@@ -27,7 +28,7 @@ fn2 (void *frame, uword_t error)
/* { dg-final { scan-assembler-times "pushl\[\\t \]*%ebp" 2 { target ia32 } } } */
/* { dg-final { scan-assembler-times "leave" 2 { target { ia32 && nonpic } } } } */
/* { dg-final { scan-assembler-times "pushl\[\\t \]*%eax" 2 { target ia32 } } } */
-/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%eax" 2 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%eax" 2 { target { ia32 && nonpic } } } } */
/* { dg-final { scan-assembler-times "pushq\[\\t \]*%rdi" 2 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "popq\[\\t \]*%rdi" 2 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler "(addl|leal).*4.*%esp" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-16.c b/gcc/testsuite/gcc.target/i386/interrupt-16.c
index bc929c6..cb45ba5 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-16.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-16.c
@@ -12,7 +12,8 @@ foo (int i)
/* { dg-final { scan-assembler-not "movups\[\\t \]*%(x|y|z)mm\[0-9\]+,\[\\t \]-*\[0-9\]*\\(%\[re\]?bp\\)" } } */
/* { dg-final { scan-assembler-not "movups\[\\t \]*-\[0-9\]*\\(%\[re\]?bp\\),\[\\t \]*%(x|y|z)mm\[0-9\]+" } } */
-/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(a|b|c|d)x" } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)bx" { target { nonpic || { ! ia32 } } } } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(a|c|d)x" } } */
/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)si" } } */
/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)bp" } } */
/* { dg-final { scan-assembler-not "(push|pop)l\[\\t \]*%edi" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-17.c b/gcc/testsuite/gcc.target/i386/interrupt-17.c
index 5d5b59e..218ed60 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-17.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-17.c
@@ -11,7 +11,8 @@ foo (int i)
}
/* { dg-final { scan-assembler-not "movups\[\\t \]*%(x|y|z)mm\[0-9\]+" } } */
-/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(a|b|c|d)x" } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)bx" { target { nonpic || { ! ia32 } } } } } */
+/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)(a|c|d)x" } } */
/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)si" } } */
/* { dg-final { scan-assembler-not "(push|pop)(l|q)\[\\t \]*%(r|e)bp" } } */
/* { dg-final { scan-assembler-not "(push|pop)l\[\\t \]*%edi" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-8.c b/gcc/testsuite/gcc.target/i386/interrupt-8.c
index 34536d1..039ccd5 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-8.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-8.c
@@ -15,7 +15,7 @@ foo (void *frame)
/* { dg-final { scan-assembler-not "kmov.\[\\t \]*\[0-9\]*\\(%\[re\]?sp\\),\[\\t \]*%k\[0-7\]+" } } */
/* { dg-final { scan-assembler-not "pushq\[\\t \]*%rbx" { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-not "pushq\[\\t \]*%r1\[2-5\]+" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "pushl\[\\t \]*%ebx" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "pushl\[\\t \]*%ebx" { target { ia32 && nonpic } } } } */
/* { dg-final { scan-assembler-not "pushl\[\\t \]*%e(s|d)i" { target ia32 } } } */
/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)ax" 1 } } */
/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)cx" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pad-10.c b/gcc/testsuite/gcc.target/i386/pad-10.c
index 3d003a8..ac015f2 100644
--- a/gcc/testsuite/gcc.target/i386/pad-10.c
+++ b/gcc/testsuite/gcc.target/i386/pad-10.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-march=*" } { "-march=atom" } } */
/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */
-/* { dg-final { scan-assembler-not "nop" } } */
+/* { dg-final { scan-assembler-not "nop" { target { nonpic || { ! ia32 } } } } } */
/* { dg-final { scan-assembler-not "rep" } } */
extern void bar ();
diff --git a/gcc/testsuite/gcc.target/i386/pr100704-3.c b/gcc/testsuite/gcc.target/i386/pr100704-3.c
index 65f9745..6f7a3e5 100644
--- a/gcc/testsuite/gcc.target/i386/pr100704-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr100704-3.c
@@ -17,4 +17,6 @@ foo (void)
bar (1, 2, 3, 4, 5, 6, foooo[0]);
}
-/* { dg-final { scan-assembler "push\[lq\]\tfoooo\+" } } */
+/* { dg-final { scan-assembler "push\[lq\]\tfoooo\+" { target { nonpic || { ! ia32 } } } } }*/
+/* { dg-final { scan-assembler "movl\tfoooo@GOT\\(%ebx\\), %eax" { target { ia32 && { ! nonpic } } } } } */
+/* { dg-final { scan-assembler-times "pushl\t(?:|4|8|12)\\(%eax\\)" 4 { target { ia32 && { ! nonpic } } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-2.c b/gcc/testsuite/gcc.target/i386/pr100865-2.c
index f3ea775..090a010 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=skylake" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-3.c b/gcc/testsuite/gcc.target/i386/pr100865-3.c
index 714c43e..cde4b1c 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=skylake-avx512" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-4a.c b/gcc/testsuite/gcc.target/i386/pr100865-4a.c
index 8609d11..bd99945 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-4a.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-4a.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=skylake -mtune-ctrl=avx256_store_by_pieces" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern char array[64];
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-4b.c b/gcc/testsuite/gcc.target/i386/pr100865-4b.c
index 6d9cb91..1814306 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-4b.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-4b.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=skylake-avx512" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#include "pr100865-4a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-5a.c b/gcc/testsuite/gcc.target/i386/pr100865-5a.c
index 4149797..b023fca 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-5a.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-5a.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=skylake" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern short array[64];
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-5b.c b/gcc/testsuite/gcc.target/i386/pr100865-5b.c
index ded41b68..5bccfd0 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-5b.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-5b.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=skylake-avx512" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#include "pr100865-5a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-6a.c b/gcc/testsuite/gcc.target/i386/pr100865-6a.c
index 3fde549..34951a9 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-6a.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-6a.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=skylake" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern int array[64];
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-6b.c b/gcc/testsuite/gcc.target/i386/pr100865-6b.c
index 9588249..09b0e71 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-6b.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-6b.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=skylake-avx512" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#include "pr100865-6a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-6c.c b/gcc/testsuite/gcc.target/i386/pr100865-6c.c
index 46d3103..bab7c88 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-6c.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-6c.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=skylake -mno-avx2" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern int array[64];
diff --git a/gcc/testsuite/gcc.target/i386/pr100865-7b.c b/gcc/testsuite/gcc.target/i386/pr100865-7b.c
index 3b20c68..49f752e 100644
--- a/gcc/testsuite/gcc.target/i386/pr100865-7b.c
+++ b/gcc/testsuite/gcc.target/i386/pr100865-7b.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=skylake-avx512" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#include "pr100865-7a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr101796-1.c b/gcc/testsuite/gcc.target/i386/pr101796-1.c
index 3a5f50d..b25464d 100644
--- a/gcc/testsuite/gcc.target/i386/pr101796-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr101796-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512bw" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final {scan-assembler-times "vpsrlw\[ \\t\]" 1 } } */
/* { dg-final {scan-assembler-times "vpsllw\[ \\t\]" 1 } } */
/* { dg-final {scan-assembler-times "vpsraw\[ \\t\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr101846-2.c b/gcc/testsuite/gcc.target/i386/pr101846-2.c
index 26c9ed5..bc2b466 100644
--- a/gcc/testsuite/gcc.target/i386/pr101846-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr101846-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512vl -mavx512vbmi -O2" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-times "vpmovwb" "3" } } */
/* { dg-final { scan-assembler-times "vpmovdw" "3" } } */
/* { dg-final { scan-assembler-times "vpmovqd" "3" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr101989-broadcast-1.c b/gcc/testsuite/gcc.target/i386/pr101989-broadcast-1.c
index d03d192..428c40c 100644
--- a/gcc/testsuite/gcc.target/i386/pr101989-broadcast-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr101989-broadcast-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mavx512vl" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-times "vpternlog" 4 } } */
/* { dg-final { scan-assembler-times "\\\{1to4\\\}" 4 } } */
#include<immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr102021.c b/gcc/testsuite/gcc.target/i386/pr102021.c
index 6db3f57..a5012a4 100644
--- a/gcc/testsuite/gcc.target/i386/pr102021.c
+++ b/gcc/testsuite/gcc.target/i386/pr102021.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=skylake-avx512" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#include<immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr106322.c b/gcc/testsuite/gcc.target/i386/pr106322.c
new file mode 100644
index 0000000..31333c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr106322.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2 -mtune=generic -march=i686" } */
+
+/* As PR106322, verify this can execute well (not abort). */
+
+#define N 64
+typedef unsigned short int uh;
+typedef unsigned short int uw;
+uh a[N];
+uh b[N];
+uh c[N];
+uh e[N];
+
+__attribute__ ((noipa)) void
+foo ()
+{
+ for (int i = 0; i < N; i++)
+ c[i] = ((uw) b[i] * (uw) a[i]) >> 16;
+}
+
+__attribute__ ((optimize ("-O0"))) void
+init ()
+{
+ for (int i = 0; i < N; i++)
+ {
+ a[i] = (uh) (0x7ABC - 0x5 * i);
+ b[i] = (uh) (0xEAB + 0xF * i);
+ e[i] = ((uw) b[i] * (uw) a[i]) >> 16;
+ }
+}
+
+__attribute__ ((optimize ("-O0"))) void
+check ()
+{
+ for (int i = 0; i < N; i++)
+ {
+ if (c[i] != e[i])
+ __builtin_abort ();
+ }
+}
+
+int
+main ()
+{
+ init ();
+ foo ();
+ check ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr15184-1.c b/gcc/testsuite/gcc.target/i386/pr15184-1.c
index 8c19e47..756183d 100644
--- a/gcc/testsuite/gcc.target/i386/pr15184-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr15184-1.c
@@ -1,6 +1,7 @@
/* PR 15184 first two tests, plus two addition ones. */
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2 -march=pentiumpro" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#define regparm __attribute__((__regparm__(1)))
diff --git a/gcc/testsuite/gcc.target/i386/pr15184-2.c b/gcc/testsuite/gcc.target/i386/pr15184-2.c
index a6cb9eb..cb8201f 100644
--- a/gcc/testsuite/gcc.target/i386/pr15184-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr15184-2.c
@@ -1,6 +1,7 @@
/* PR 15184 second two tests
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2 -march=pentiumpro" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
#define regparm __attribute__((__regparm__(1)))
diff --git a/gcc/testsuite/gcc.target/i386/pr27971.c b/gcc/testsuite/gcc.target/i386/pr27971.c
index f80cb65..19eb354 100644
--- a/gcc/testsuite/gcc.target/i386/pr27971.c
+++ b/gcc/testsuite/gcc.target/i386/pr27971.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-tbm" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-additional-options "-mdynamic-no-pic" { target { *-*-darwin* && ia32 } } } */
unsigned array[4];
@@ -17,4 +18,3 @@ unsigned foo(TYPE x)
/* { dg-final { scan-assembler-not "shr\[^\\n\]*2" } } */
/* { dg-final { scan-assembler "and\[^\\n\]*12" } } */
- \ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-3.c b/gcc/testsuite/gcc.target/i386/pr54855-3.c
index 3c15dfc9..a58a8ba 100644
--- a/gcc/testsuite/gcc.target/i386/pr54855-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr54855-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-times "subsd" 1 } } */
/* { dg-final { scan-assembler-not "movapd" } } */
/* { dg-final { scan-assembler-not "movsd" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-7.c b/gcc/testsuite/gcc.target/i386/pr54855-7.c
index a551bd5..d9ef66a 100644
--- a/gcc/testsuite/gcc.target/i386/pr54855-7.c
+++ b/gcc/testsuite/gcc.target/i386/pr54855-7.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -msse -mfpmath=sse" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-times "divss" 1 } } */
/* { dg-final { scan-assembler-not "movaps" } } */
/* { dg-final { scan-assembler-not "movss" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr70263-2.c b/gcc/testsuite/gcc.target/i386/pr70263-2.c
index 19f79fd..20447ed 100644
--- a/gcc/testsuite/gcc.target/i386/pr70263-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr70263-2.c
@@ -1,5 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-rtl-ira" } */
+/* ia32 PIC prevents tail-calling, which forces bar's arg to be pushed, which
+ drops the equivalence. */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-rtl-dump "Adding REG_EQUIV to insn \[0-9\]+ for source of insn \[0-9\]+" "ira" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr70321.c b/gcc/testsuite/gcc.target/i386/pr70321.c
index eaba728..57552ef 100644
--- a/gcc/testsuite/gcc.target/i386/pr70321.c
+++ b/gcc/testsuite/gcc.target/i386/pr70321.c
@@ -7,4 +7,6 @@ void foo (long long ixi)
__builtin_abort ();
}
-/* { dg-final { scan-assembler-times "mov" 1 } } */
+/* { dg-final { scan-assembler-times "mov" 1 { target nonpic } } } */
+/* get_pc_thunk adds an extra mov insn. */
+/* { dg-final { scan-assembler-times "mov" 2 { target { ! nonpic } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78035.c b/gcc/testsuite/gcc.target/i386/pr78035.c
index 2e673a8..7d3a983 100644
--- a/gcc/testsuite/gcc.target/i386/pr78035.c
+++ b/gcc/testsuite/gcc.target/i386/pr78035.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern int a;
extern int b;
diff --git a/gcc/testsuite/gcc.target/i386/pr81563.c b/gcc/testsuite/gcc.target/i386/pr81563.c
index f0efcf9..3d3f959 100644
--- a/gcc/testsuite/gcc.target/i386/pr81563.c
+++ b/gcc/testsuite/gcc.target/i386/pr81563.c
@@ -10,4 +10,4 @@ fn1 (long long int x)
return x;
}
-/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]*\\(%esp\\)" } } */
+/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\\(%esp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81736-5.c b/gcc/testsuite/gcc.target/i386/pr81736-5.c
index e1602cf..0dcf17b 100644
--- a/gcc/testsuite/gcc.target/i386/pr81736-5.c
+++ b/gcc/testsuite/gcc.target/i386/pr81736-5.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fno-omit-frame-pointer -mavx" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
typedef int v8si __attribute__ ((vector_size (32)));
diff --git a/gcc/testsuite/gcc.target/i386/pr81736-7.c b/gcc/testsuite/gcc.target/i386/pr81736-7.c
index f947886..95b380d 100644
--- a/gcc/testsuite/gcc.target/i386/pr81736-7.c
+++ b/gcc/testsuite/gcc.target/i386/pr81736-7.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fno-omit-frame-pointer" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern int foo (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr84278.c b/gcc/testsuite/gcc.target/i386/pr84278.c
index d100dff..2fa8480 100644
--- a/gcc/testsuite/gcc.target/i386/pr84278.c
+++ b/gcc/testsuite/gcc.target/i386/pr84278.c
@@ -15,4 +15,6 @@ void foo(void)
}
}
-/* { dg-final { scan-assembler-not "\\\(%.sp\\\)" } } */
+/* { dg-final { scan-assembler-not "\\\(%.sp\\\)" { target { nonpic || { ! ia32 } } } } } */
+/* ia32's get_pc_thunk variants all load from %(esp). */
+/* { dg-final { scan-assembler-times "movl\[ \t]*\\\(%.sp\\\)" 1 { target { ! { nonpic || { ! ia32 } } } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr85620-6.c b/gcc/testsuite/gcc.target/i386/pr85620-6.c
index 0b6a64e..4f04ba0 100644
--- a/gcc/testsuite/gcc.target/i386/pr85620-6.c
+++ b/gcc/testsuite/gcc.target/i386/pr85620-6.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler "jmp" } } */
struct ucontext;
diff --git a/gcc/testsuite/gcc.target/i386/pr85667-6.c b/gcc/testsuite/gcc.target/i386/pr85667-6.c
index 5d2c66e..06570dd 100644
--- a/gcc/testsuite/gcc.target/i386/pr85667-6.c
+++ b/gcc/testsuite/gcc.target/i386/pr85667-6.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-times "movl\[^\n\r]*, %eax" 1 } } */
/* { dg-final { scan-assembler-times "flds\[^\n\r]*" 1 } } */
typedef struct
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-17.c b/gcc/testsuite/gcc.target/i386/pr90773-17.c
index 57074836..3036085 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-17.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-17.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=skylake-avx512" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
extern char *dst;
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-2.c b/gcc/testsuite/gcc.target/i386/pr90773-2.c
index 6449575..b5373ca 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-2.c
@@ -13,7 +13,10 @@ foo (void)
/* { dg-final { scan-assembler-times "movdqu\[\\t \]+\\(%\[\^,\]+\\)," 1 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "movl\[\\t \]+15\\(%\[\^,\]+\\)," 1 { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-times "movl\[\\t \]+\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
+/* PIC gets one extra match in get_pc_thunk, and two extra matches to load
+ dst's and src's values after loading their addresses from the GOT. */
+/* { dg-final { scan-assembler-times "movl\[\\t \]+\\(%\[\^,\]+\\)," 1 { target { ia32 && nonpic } } } } */
+/* { dg-final { scan-assembler-times "movl\[\\t \]+\\(%\[\^,\]+\\)," 4 { target { ia32 && { ! nonpic } } } } } */
/* { dg-final { scan-assembler-times "movl\[\\t \]+4\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "movl\[\\t \]+8\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "movl\[\\t \]+12\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90773-3.c b/gcc/testsuite/gcc.target/i386/pr90773-3.c
index 84747c9..dd2430f 100644
--- a/gcc/testsuite/gcc.target/i386/pr90773-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr90773-3.c
@@ -13,7 +13,10 @@ foo (void)
/* { dg-final { scan-assembler-times "movdqu\[\\t \]+\\(%\[\^,\]+\\)," 1 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "movdqu\[\\t \]+15\\(%\[\^,\]+\\)," 1 { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-times "movl\[\\t \]+\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
+/* PIC gets one extra match in get_pc_thunk, and two extra matches to load
+ dst's and src's values after loading their addresses from the GOT. */
+/* { dg-final { scan-assembler-times "movl\[\\t \]+\\(%\[\^,\]+\\)," 1 { target { ia32 && nonpic } } } } */
+/* { dg-final { scan-assembler-times "movl\[\\t \]+\\(%\[\^,\]+\\)," 4 { target { ia32 && { ! nonpic } } } } } */
/* { dg-final { scan-assembler-times "movl\[\\t \]+4\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "movl\[\\t \]+8\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "movl\[\\t \]+12\\(%\[\^,\]+\\)," 1 { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-5.c b/gcc/testsuite/gcc.target/i386/pr93492-5.c
index 5aebb38..1ca5ba1 100644
--- a/gcc/testsuite/gcc.target/i386/pr93492-5.c
+++ b/gcc/testsuite/gcc.target/i386/pr93492-5.c
@@ -1,5 +1,6 @@
/* { dg-do "compile" { target *-*-linux* } } */
/* { dg-options "-O1 -fpatchable-function-entry=1 -mfentry -pg -fasynchronous-unwind-tables" } */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* Test the placement of the .LPFE1 label. */
diff --git a/gcc/testsuite/gcc.target/i386/pr94913-2.c b/gcc/testsuite/gcc.target/i386/pr94913-2.c
index 22bca2b..199f3fe 100644
--- a/gcc/testsuite/gcc.target/i386/pr94913-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr94913-2.c
@@ -21,4 +21,8 @@ void fooi (unsigned long x, unsigned long y)
}
/* { dg-final { scan-assembler-not "cmp" } } */
-/* { dg-final { scan-assembler-times "add" 3 } } */
+/* On IA32, PIC adds one add per function to compute the PIC register, and
+ another add to adjust %esp in the epilogue needed to restore the PIC
+ register. */
+/* { dg-final { scan-assembler-times "add" 3 { target { ! { ia32 && { ! nonpic } } } } } } */
+/* { dg-final { scan-assembler-times "add" 9 { target { ia32 && { ! nonpic } } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95126-m32-1.c b/gcc/testsuite/gcc.target/i386/pr95126-m32-1.c
index 1d6acd6..9dfe15d 100644
--- a/gcc/testsuite/gcc.target/i386/pr95126-m32-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr95126-m32-1.c
@@ -10,7 +10,8 @@ void call_func(void)
func(s);
}
-/* { dg-final { scan-assembler "movl\[ \\t]*\\\$" } } */
-/* { dg-final { scan-assembler "movb\[ \\t]*\\\$0, " } } */
-/* { dg-final { scan-assembler-not "movzwl" } } */
-
+/* The @GOTOFF addressing seems to prevent the optimization of the loads to
+ known constants. */
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$" { xfail { ! nonpic } } } } */
+/* { dg-final { scan-assembler "movb\[ \\t]*\\\$0, " { xfail { ! nonpic } } } } */
+/* { dg-final { scan-assembler-not "movzwl" { xfail { ! nonpic } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95126-m32-2.c b/gcc/testsuite/gcc.target/i386/pr95126-m32-2.c
index b46be9d..f4d9123 100644
--- a/gcc/testsuite/gcc.target/i386/pr95126-m32-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr95126-m32-2.c
@@ -10,7 +10,8 @@ void call_func(void)
func(s);
}
-/* { dg-final { scan-assembler "movl\[ \\t]*\\\$" } } */
-/* { dg-final { scan-assembler "movb\[ \\t]*\\\$0, " } } */
-/* { dg-final { scan-assembler-not "movzwl" } } */
-
+/* The @GOTOFF addressing seems to prevent the optimization of the loads to
+ known constants. */
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$" { xfail { ! nonpic } } } } */
+/* { dg-final { scan-assembler "movb\[ \\t]*\\\$0, " { xfail { ! nonpic } } } } */
+/* { dg-final { scan-assembler-not "movzwl" { xfail { ! nonpic } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95852-2.c b/gcc/testsuite/gcc.target/i386/pr95852-2.c
index de85cec..558308f 100644
--- a/gcc/testsuite/gcc.target/i386/pr95852-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr95852-2.c
@@ -3,7 +3,13 @@
/* { dg-options "-O2 -fdump-tree-optimized -masm=att" } */
/* { dg-final { scan-tree-dump-times " = \.MUL_OVERFLOW " 32 "optimized" } } */
/* { dg-final { scan-assembler-times "\tmull\t" 32 } } */
-/* { dg-final { scan-assembler-times "\tseto\t" 8 } } */
+/* In functions that return 0 on non-overflow (f2, f10, f18, f26), the overflow
+ flag is propagated to the return value's PHI node in the non-call path; on
+ ia32 PIC, sibcalls are not viable, so the known value of the flag can't be
+ propagated to the return block, that is only duplicated in bbro, too late
+ for fwprop2 or even cprop_hardreg. */
+/* { dg-final { scan-assembler-times "\tseto\t" 12 { target { ia32 && { ! nonpic } } } } } */
+/* { dg-final { scan-assembler-times "\tseto\t" 8 { target { nonpic || { ! ia32 } } } } } */
/* { dg-final { scan-assembler-times "\tsetno\t" 8 } } */
/* { dg-final { scan-assembler-times "\tjn\?o\t" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr95852-4.c b/gcc/testsuite/gcc.target/i386/pr95852-4.c
index f8b4656..cb48b61 100644
--- a/gcc/testsuite/gcc.target/i386/pr95852-4.c
+++ b/gcc/testsuite/gcc.target/i386/pr95852-4.c
@@ -3,7 +3,13 @@
/* { dg-options "-O2 -fdump-tree-optimized -masm=att" } */
/* { dg-final { scan-tree-dump-times " = \.MUL_OVERFLOW " 32 "optimized" } } */
/* { dg-final { scan-assembler-times "\timull\t" 32 } } */
-/* { dg-final { scan-assembler-times "\tseto\t" 8 } } */
+/* In functions that return 0 on non-overflow (f2, f10, f18, f26), the overflow
+ flag is propagated to the return value's PHI node in the non-call path; on
+ ia32 PIC, sibcalls are not viable, so the known value of the flag can't be
+ propagated to the return block, that is only duplicated in bbro, too late
+ for fwprop2 or even cprop_hardreg. */
+/* { dg-final { scan-assembler-times "\tseto\t" 12 { target { ia32 && { ! nonpic } } } } } */
+/* { dg-final { scan-assembler-times "\tseto\t" 8 { target { nonpic || { ! ia32 } } } } } */
/* { dg-final { scan-assembler-times "\tsetno\t" 8 } } */
/* { dg-final { scan-assembler-times "\tjn\?o\t" 16 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr96539.c b/gcc/testsuite/gcc.target/i386/pr96539.c
index fc164f8..696929b 100644
--- a/gcc/testsuite/gcc.target/i386/pr96539.c
+++ b/gcc/testsuite/gcc.target/i386/pr96539.c
@@ -1,6 +1,9 @@
/* PR rtl-optimization/96539 */
/* { dg-do compile } *
/* { dg-options "-Os" } */
+/* The need to restore the PIC register prevents PLT tail-calls on ia32,
+ so S has to be copied to call baz. */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
/* { dg-final { scan-assembler-not "rep\[^\n\r]\*movs" } } */
struct A { int a, b, c, d, e, f; void *g, *h, *i, *j, *k, *l, *m; };
diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c
new file mode 100644
index 0000000..612d55b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse2" } */
+
+__bf16/* { dg-error "unknown type name '__bf16'" } */
+foo (__bf16 x) /* { dg-error "unknown type name '__bf16'" } */
+{
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c
new file mode 100644
index 0000000..a3286e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-avx512f" } */
+
+union flt
+{
+ __bf16 flt;
+ short s;
+};
+
+__bf16
+foo (union flt x)
+{
+ return x.flt;
+}
+
+/* { dg-final { scan-assembler {(?n)pinsrw[\t ].*%xmm0} { target ia32 } } } */
+/* { dg-final { scan-assembler {(?n)movd[\t ].*%xmm0} { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
new file mode 100644
index 0000000..f76d554
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
@@ -0,0 +1,215 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+
+
+__bf16 glob_bfloat;
+
+int is_an_int;
+short is_a_short_int;
+float is_a_float;
+float is_a_float16;
+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 footest (__bf16 scalar0)
+{
+
+ /* Initialisation */
+
+ __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 scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */
+ __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'} } */
+
+ /* 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'} } */
+
+ /* 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'} } */
+
+ (__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'} } */
+
+ /* Compound literals. */
+
+ (__bf16) {}; /* { dg-error {empty scalar initializer} } */
+ (__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'} } */
+
+ /* Arrays and Structs. */
+
+ typedef __bf16 array_type[2];
+ extern __bf16 extern_array[];
+
+ __bf16 array[2];
+ __bf16 zero_length_array[0];
+ __bf16 empty_init_array[] = {};
+ typedef __bf16 some_other_type[is_an_int];
+
+ struct struct1 {
+ __bf16 a;
+ };
+
+ union union1 {
+ __bf16 a;
+ };
+
+ /* Addressing and dereferencing. */
+
+ __bf16 *bfloat_ptr = &scalar0;
+ scalar0 = *bfloat_ptr;
+
+ /* Pointer assignment. */
+
+ __bf16 *bfloat_ptr2 = bfloat_ptr;
+ __bf16 *bfloat_ptr3 = array;
+
+ /* Pointer arithmetic. */
+
+ ++bfloat_ptr;
+ --bfloat_ptr;
+ bfloat_ptr++;
+ bfloat_ptr--;
+ bfloat_ptr += 1;
+ bfloat_ptr -= 1;
+ bfloat_ptr - bfloat_ptr2;
+ bfloat_ptr = &bfloat_ptr3[0];
+ 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'} } */
+
+ /* Pointer comparison. */
+
+ bfloat_ptr == &scalar0;
+ bfloat_ptr != &scalar0;
+ bfloat_ptr < &scalar0;
+ bfloat_ptr <= &scalar0;
+ bfloat_ptr > &scalar0;
+ bfloat_ptr >= &scalar0;
+ bfloat_ptr == bfloat_ptr2;
+ bfloat_ptr != bfloat_ptr2;
+ bfloat_ptr < bfloat_ptr2;
+ bfloat_ptr <= bfloat_ptr2;
+ bfloat_ptr > bfloat_ptr2;
+ bfloat_ptr >= bfloat_ptr2;
+
+ /* 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 ? 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'} } */
+
+ /* 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; /* { 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'} } */
+
+ /* 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'} } */
+
+ return scalar0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-stv-9.c b/gcc/testsuite/gcc.target/i386/sse4_1-stv-9.c
new file mode 100644
index 0000000..ee5af3c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-stv-9.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -msse4.1 -mstv -mno-stackrealign" } */
+
+unsigned __int128 a, b;
+void rot1() { a = (b >> 1) | (b << 127); }
+void rot4() { a = (b >> 4) | (b << 124); }
+void rot8() { a = (b >> 8) | (b << 120); }
+void rot32() { a = (b >> 32) | (b << 96); }
+void rot64() { a = (b >> 64) | (b << 64); }
+
+/* { dg-final { scan-assembler-not "shrdq" } } */
+/* { dg-final { scan-assembler "pshufd" } } */
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-12.c b/gcc/testsuite/gcc.target/i386/stack-check-12.c
index 74d3a26..aa9c233 100644
--- a/gcc/testsuite/gcc.target/i386/stack-check-12.c
+++ b/gcc/testsuite/gcc.target/i386/stack-check-12.c
@@ -11,8 +11,9 @@ f (void)
}
/* { dg-final { scan-assembler-not "or\[ql\]" } } */
-/* { dg-final { scan-assembler "pushl %esi" { target ia32 } } } */
-/* { dg-final { scan-assembler "popl %esi" { target ia32 } } }*/
+/* On ia32 PIC, saving the PIC register requires a stack frame, which does away
+ with the need for the dummy %esi pushing and popping for stack probing. */
+/* { dg-final { scan-assembler "pushl %esi" { target { ia32 && nonpic } } } } */
+/* { dg-final { scan-assembler "popl %esi" { target { ia32 && nonpic } } } } */
/* { dg-final { scan-assembler "pushq %rax" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler "popq %rax" { target { ! ia32 } } } }*/
-
+/* { dg-final { scan-assembler "popq %rax" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-17.c b/gcc/testsuite/gcc.target/i386/stack-check-17.c
index 25ae977..b3e41cb 100644
--- a/gcc/testsuite/gcc.target/i386/stack-check-17.c
+++ b/gcc/testsuite/gcc.target/i386/stack-check-17.c
@@ -31,9 +31,11 @@ f3 (void)
into either a stack slot or callee saved register. The former
would be rather dumb. So assume it does not happen.
- So search for two/four pushes for the callee register saves/argument
- pushes and no pops (since the function has no reachable epilogue). */
+ So search for two/four pushes for the callee register saves/argument pushes
+ (plus one for the PIC register if needed on ia32) and no pops (since the
+ function has no reachable epilogue). */
/* { dg-final { scan-assembler-times "push\[ql\]" 2 { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-times "push\[ql\]" 4 { target { ia32 } } } } */
+/* { dg-final { scan-assembler-times "push\[ql\]" 4 { target { ia32 && nonpic } } } } */
+/* { dg-final { scan-assembler-times "push\[ql\]" 5 { target { ia32 && { ! nonpic } } } } } */
/* { dg-final { scan-assembler-not "pop" } } */
diff --git a/gcc/testsuite/gcc.target/i386/stack-prot-sym.c b/gcc/testsuite/gcc.target/i386/stack-prot-sym.c
index dcd7cbd..81790f6 100644
--- a/gcc/testsuite/gcc.target/i386/stack-prot-sym.c
+++ b/gcc/testsuite/gcc.target/i386/stack-prot-sym.c
@@ -1,6 +1,8 @@
/* { dg-do compile } */
/* { dg-require-effective-target tls_native } */
/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=tls -mstack-protector-guard-reg=gs -mstack-protector-guard-symbol=my_guard" } */
+/* We don't expect GOT relocations; should we? */
+/* { dg-additional-options "-fno-PIE" { target ia32 } } */
void f(void) { }
diff --git a/gcc/testsuite/gcc.target/powerpc/pr103353.c b/gcc/testsuite/gcc.target/powerpc/pr103353.c
new file mode 100644
index 0000000..5d519fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr103353.c
@@ -0,0 +1,22 @@
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* If the default cpu type is power10 or later, MMA is enabled by default.
+ To keep the test point available all the time, this case specifies
+ -mdejagnu-cpu=power6 to make it be tested without MMA. */
+/* { dg-options "-maltivec -mdejagnu-cpu=power6" } */
+
+/* Verify there is no ICE and don't check the error messages on MMA
+ requirement since they could be fragile and are not test points
+ of this case. */
+/* { dg-excess-errors "pr103353" } */
+
+void
+foo (__vector_pair *dst, double *x)
+{
+ dst[0] = __builtin_vsx_lxvp (0, (__vector_pair *)(void *)x);
+}
+
+void
+bar (__vector_pair *src, double *x)
+{
+ __builtin_vsx_stxvp (src[0], 0, (__vector_pair *)(void *)x);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr106322.c b/gcc/testsuite/gcc.target/powerpc/pr106322.c
new file mode 100644
index 0000000..c05072d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr106322.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mdejagnu-cpu=power4" } */
+
+/* As PR106322, verify this can execute well (not abort). */
+
+#define N 64
+typedef unsigned short int uh;
+typedef unsigned short int uw;
+uh a[N];
+uh b[N];
+uh c[N];
+uh e[N];
+
+__attribute__ ((noipa)) void
+foo ()
+{
+ for (int i = 0; i < N; i++)
+ c[i] = ((uw) b[i] * (uw) a[i]) >> 16;
+}
+
+__attribute__ ((optimize ("-O0"))) void
+init ()
+{
+ for (int i = 0; i < N; i++)
+ {
+ a[i] = (uh) (0x7ABC - 0x5 * i);
+ b[i] = (uh) (0xEAB + 0xF * i);
+ e[i] = ((uw) b[i] * (uw) a[i]) >> 16;
+ }
+}
+
+__attribute__ ((optimize ("-O0"))) void
+check ()
+{
+ for (int i = 0; i < N; i++)
+ {
+ if (c[i] != e[i])
+ __builtin_abort ();
+ }
+}
+
+int
+main ()
+{
+ init ();
+ foo ();
+ check ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.dg/torture/pr106623.d b/gcc/testsuite/gdc.dg/torture/pr106623.d
new file mode 100644
index 0000000..d782b23
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/torture/pr106623.d
@@ -0,0 +1,28 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106623
+// { dg-do compile }
+private struct _Complex(T) { T re; T im; }
+enum __c_complex_double : _Complex!double;
+
+pragma(inline, true)
+ulong hashOf()(scope const double val)
+{
+ return *cast(ulong*)&val;
+}
+
+pragma(inline, true)
+ulong hashOf()(scope const _Complex!double val, ulong seed = 0)
+{
+ return hashOf(val.re) + hashOf(val.im);
+}
+
+pragma(inline, true)
+ulong hashOf()(__c_complex_double val, ulong seed = 0)
+{
+ return hashOf(cast(_Complex!double) val, seed);
+}
+
+ulong test106623()
+{
+ __c_complex_double val;
+ return hashOf(val);
+}
diff --git a/gcc/tree-ssa-loop.h b/gcc/tree-ssa-loop.h
index 415f461..6c70f79 100644
--- a/gcc/tree-ssa-loop.h
+++ b/gcc/tree-ssa-loop.h
@@ -54,11 +54,11 @@ public:
widest_int max; /* The upper bound on the number of iterations of
the loop. */
- /* The simplified shape of the exit condition. The loop exits if
- CONTROL CMP BOUND is false, where CMP is one of NE_EXPR,
- LT_EXPR, or GT_EXPR, and step of CONTROL is positive if CMP is
- LE_EXPR and negative if CMP is GE_EXPR. This information is used
- by loop unrolling. */
+ /* The simplified shape of the exit condition. This information is used by
+ loop unrolling. If CMP is ERROR_MARK, then the loop cannot be unrolled.
+ Otherwise, the loop exits if CONTROL CMP BOUND is false, where CMP is one
+ of NE_EXPR, LT_EXPR, or GT_EXPR, and CONTROL.STEP is positive if CMP is
+ LT_EXPR and negative if CMP is GT_EXPR. */
affine_iv control;
tree bound;
enum tree_code cmp;
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 0191b9c..d5f2ba8 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -2448,8 +2448,6 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
return false;
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig_use_lhs))
return false;
- if (EDGE_COUNT (phi_bb->preds) != 4)
- return false;
if (!single_imm_use (orig_use_lhs, &use_p, &use_stmt))
return false;
@@ -2467,8 +2465,6 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
orig_use_lhs = gimple_assign_lhs (use_stmt);
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig_use_lhs))
return false;
- if (EDGE_COUNT (phi_bb->preds) != 4)
- return false;
if (!single_imm_use (orig_use_lhs, &use_p, &use_stmt))
return false;
}
diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc
index 30047c6..b886027 100644
--- a/gcc/tree-ssa-threadbackward.cc
+++ b/gcc/tree-ssa-threadbackward.cc
@@ -362,32 +362,85 @@ back_threader::find_paths_to_names (basic_block bb, bitmap interesting,
{
// For further greedy searching we want to remove interesting
// names defined in BB but add ones on the PHI edges for the
- // respective edges. We do this by starting with all names
+ // respective edges and adding imports from those stmts.
+ // We do this by starting with all names
// not defined in BB as interesting, collecting a list of
// interesting PHIs in BB on the fly. Then we iterate over
// predecessor edges, adding interesting PHI edge defs to
// the set of interesting names to consider when processing it.
auto_bitmap new_interesting;
+ auto_vec<int, 16> new_imports;
auto_vec<gphi *, 4> interesting_phis;
bitmap_iterator bi;
unsigned i;
+ auto_vec<tree, 16> worklist;
EXECUTE_IF_SET_IN_BITMAP (interesting, 0, i, bi)
{
tree name = ssa_name (i);
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+ /* Imports remain interesting. */
if (gimple_bb (def_stmt) != bb)
- bitmap_set_bit (new_interesting, i);
- else if (gphi *phi = dyn_cast<gphi *> (def_stmt))
{
- tree res = gimple_phi_result (phi);
- if (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (res))
- interesting_phis.safe_push (phi);
+ bitmap_set_bit (new_interesting, i);
+ continue;
+ }
+ worklist.quick_push (name);
+ while (!worklist.is_empty ())
+ {
+ tree name = worklist.pop ();
+ gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+ /* Newly discovered imports are interesting. */
+ if (gimple_bb (def_stmt) != bb)
+ {
+ bitmap_set_bit (new_interesting, SSA_NAME_VERSION (name));
+ continue;
+ }
+ /* Local PHIs participate in renaming below. */
+ if (gphi *phi = dyn_cast<gphi *> (def_stmt))
+ {
+ tree res = gimple_phi_result (phi);
+ if (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (res))
+ interesting_phis.safe_push (phi);
+ }
+ /* For other local defs process their uses, amending
+ imports on the way. */
+ else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
+ {
+ tree ssa[3];
+ if (range_op_handler (ass))
+ {
+ ssa[0] = gimple_range_ssa_p (gimple_range_operand1 (ass));
+ ssa[1] = gimple_range_ssa_p (gimple_range_operand2 (ass));
+ ssa[2] = NULL_TREE;
+ }
+ else if (gimple_assign_rhs_code (ass) == COND_EXPR)
+ {
+ ssa[0] = gimple_range_ssa_p (gimple_assign_rhs1 (ass));
+ ssa[1] = gimple_range_ssa_p (gimple_assign_rhs2 (ass));
+ ssa[2] = gimple_range_ssa_p (gimple_assign_rhs3 (ass));
+ }
+ else
+ continue;
+ for (unsigned j = 0; j < 3; ++j)
+ {
+ tree rhs = ssa[j];
+ if (rhs
+ && TREE_CODE (rhs) == SSA_NAME
+ && bitmap_set_bit (m_imports,
+ SSA_NAME_VERSION (rhs)))
+ {
+ new_imports.safe_push (SSA_NAME_VERSION (rhs));
+ worklist.safe_push (rhs);
+ }
+ }
+ }
}
}
if (!bitmap_empty_p (new_interesting)
|| !interesting_phis.is_empty ())
{
- auto_vec<tree, 4> unwind (interesting_phis.length ());
+ auto_vec<int, 4> unwind (interesting_phis.length ());
+ auto_vec<int, 4> imports_unwind (interesting_phis.length ());
edge_iterator iter;
edge e;
FOR_EACH_EDGE (e, iter, bb->preds)
@@ -405,22 +458,31 @@ back_threader::find_paths_to_names (basic_block bb, bitmap interesting,
{
tree def = PHI_ARG_DEF_FROM_EDGE (phi, e);
if (TREE_CODE (def) == SSA_NAME)
- if (bitmap_set_bit (new_interesting,
- SSA_NAME_VERSION (def)))
- {
- bitmap_set_bit (m_imports, SSA_NAME_VERSION (def));
- unwind.quick_push (def);
- }
+ {
+ int ver = SSA_NAME_VERSION (def);
+ if (bitmap_set_bit (new_interesting, ver))
+ {
+ if (bitmap_set_bit (m_imports, ver))
+ imports_unwind.quick_push (ver);
+ unwind.quick_push (ver);
+ }
+ }
}
find_paths_to_names (e->src, new_interesting, overall_paths);
- // Restore new_interesting. We leave m_imports alone since
- // we do not prune defs in BB from it and separately keeping
- // track of which bits to unwind isn't worth the trouble.
- for (tree def : unwind)
- bitmap_clear_bit (new_interesting, SSA_NAME_VERSION (def));
+ // Restore new_interesting.
+ for (int def : unwind)
+ bitmap_clear_bit (new_interesting, def);
unwind.truncate (0);
+ // Restore and m_imports.
+ for (int def : imports_unwind)
+ bitmap_clear_bit (m_imports, def);
+ imports_unwind.truncate (0);
}
}
+ /* m_imports tracks all interesting names on the path, so when
+ backtracking we have to restore it. */
+ for (int j : new_imports)
+ bitmap_clear_bit (m_imports, j);
}
else if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " FAIL: Search space limit %d reached.\n",
@@ -444,15 +506,28 @@ back_threader::find_paths (basic_block bb, tree name)
&& gimple_code (stmt) != GIMPLE_SWITCH))
return;
- if (EDGE_COUNT (bb->succs) > 1
- || single_succ_to_potentially_threadable_block (bb))
+ if (EDGE_COUNT (bb->succs) > 1)
{
m_last_stmt = stmt;
m_visited_bbs.empty ();
m_path.truncate (0);
m_name = name;
- m_solver->compute_imports (m_imports, bb);
+ // We compute imports of the path during discovery starting
+ // just with names used in the conditional.
+ bitmap_clear (m_imports);
+ ssa_op_iter iter;
+ FOR_EACH_SSA_TREE_OPERAND (name, stmt, iter, SSA_OP_USE)
+ {
+ if (!gimple_range_ssa_p (name))
+ return;
+ bitmap_set_bit (m_imports, SSA_NAME_VERSION (name));
+ }
+
+ // Interesting is the set of imports we still not have see
+ // the definition of. So while imports only grow, the
+ // set of interesting defs dwindles and once empty we can
+ // stop searching.
auto_bitmap interesting;
bitmap_copy (interesting, m_imports);
find_paths_to_names (bb, interesting, 1);
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index f582d23..c9dab21 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -3423,6 +3423,14 @@ vectorizable_call (vec_info *vinfo,
return false;
}
+ if (vect_emulated_vector_p (vectype_in) || vect_emulated_vector_p (vectype_out))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "use emulated vector type for call\n");
+ return false;
+ }
+
/* FORNOW */
nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index a2273f5..d056f73 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -716,25 +716,6 @@ irange::irange_set_anti_range (tree min, tree max)
void
irange::set (tree min, tree max, value_range_kind kind)
{
- if (kind != VR_UNDEFINED)
- {
- if (TREE_OVERFLOW_P (min))
- min = drop_tree_overflow (min);
- if (TREE_OVERFLOW_P (max))
- max = drop_tree_overflow (max);
- }
-
- if (!legacy_mode_p ())
- {
- if (kind == VR_RANGE)
- irange_set (min, max);
- else
- {
- gcc_checking_assert (kind == VR_ANTI_RANGE);
- irange_set_anti_range (min, max);
- }
- return;
- }
if (kind == VR_UNDEFINED)
{
irange::set_undefined ();
@@ -749,6 +730,22 @@ irange::set (tree min, tree max, value_range_kind kind)
return;
}
+ if (TREE_OVERFLOW_P (min))
+ min = drop_tree_overflow (min);
+ if (TREE_OVERFLOW_P (max))
+ max = drop_tree_overflow (max);
+
+ if (!legacy_mode_p ())
+ {
+ if (kind == VR_RANGE)
+ irange_set (min, max);
+ else
+ {
+ gcc_checking_assert (kind == VR_ANTI_RANGE);
+ irange_set_anti_range (min, max);
+ }
+ return;
+ }
// Nothing to canonicalize for symbolic ranges.
if (TREE_CODE (min) != INTEGER_CST
|| TREE_CODE (max) != INTEGER_CST)