aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog225
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog295
-rw-r--r--gcc/ada/gcc-interface/Makefile.in30
-rw-r--r--gcc/ada/libgnat/system-linux-loongarch.ads1
-rw-r--r--gcc/c-family/c-common.cc49
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def2
-rw-r--r--gcc/config/aarch64/aarch64-protos.h2
-rw-r--r--gcc/config/aarch64/aarch64-simd.md2
-rw-r--r--gcc/config/aarch64/aarch64-sme.md2
-rw-r--r--gcc/config/aarch64/aarch64.cc39
-rw-r--r--gcc/config/aarch64/aarch64.h3
-rw-r--r--gcc/config/aarch64/aarch64.md570
-rw-r--r--gcc/config/aarch64/constraints.md18
-rw-r--r--gcc/config/aarch64/iterators.md30
-rw-r--r--gcc/config/i386/i386.cc52
-rw-r--r--gcc/config/loongarch/loongarch.md3
-rw-r--r--gcc/config/riscv/riscv.cc215
-rw-r--r--gcc/config/s390/s390.cc169
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/lambda.cc13
-rw-r--r--gcc/cp/parser.cc5
-rw-r--r--gcc/cp/typeck.cc2
-rw-r--r--gcc/doc/invoke.texi3
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/match.pd13
-rw-r--r--gcc/testsuite/ChangeLog85
-rw-r--r--gcc/testsuite/c-c++-common/gomp/omp_get_num_devices_initial_device.c4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3a.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/this1.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-targ16.C29
-rw-r--r--gcc/testsuite/g++.dg/parse/pr120940.C18
-rw-r--r--gcc/testsuite/g++.dg/warn/Wduplicated-branches9.C11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr120807.c20
-rw-r--r--gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c233
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr120295.c4
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/pr120837.c32
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cmpbr.c1824
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-10.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-11.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-12.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-3.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-4.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-5.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-6.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-7.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-8.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120936-9.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr93492-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr93492-5.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_arith.h12
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c57
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c54
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c48
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c49
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c48
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c48
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c48
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c49
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c9
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c9
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/vec-perm-merge-1.c242
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/vec-perm-pack-1.c133
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/omp_get_num_devices_initial_device.f904
-rw-r--r--gcc/testsuite/lib/target-supports.exp14
-rw-r--r--gcc/tree-object-size.cc90
70 files changed, 4842 insertions, 384 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 94cb5ae..3d625ce 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,228 @@
+2025-07-03 Juergen Christ <jchrist@linux.ibm.com>
+
+ * config/s390/s390.cc (expand_perm_with_merge): Add size change cases.
+ (expand_perm_with_pack): New function.
+ (vectorize_vec_perm_const_1): Wire up new function.
+
+2025-07-03 Co-authored-by: Daniel Barboza <dbarboza@ventanamicro.com>
+ Co-authored-by: Shreya Munnangi <smunnangi1@ventanamicro.com>
+
+ PR target/118886
+ * config/riscv/riscv.cc (riscv_macro_fusion_pair_p): Check
+ for fusion being disabled earlier. If PREV is already fused,
+ then it can't be fused again. Be more selective about fusing
+ when the destination registers do not match. Don't fuse into
+ loads that aren't scalar integer modes. Revamp store pair
+ commit support.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64.md (aarch64_cbz<optab><mode>1): Move
+ above rules for CBB<cond>/CBH<cond>/CB<cond>.
+ (*aarch64_tbz<optab><mode>1): Likewise.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64-protos.h (aarch64_cb_rhs): New function.
+ * config/aarch64/aarch64.cc (aarch64_cb_rhs): Likewise.
+ * config/aarch64/aarch64.md (cbranch<mode>4): Rename to ...
+ (cbranch<GPI:mode>4): ...here, and emit CMPBR if possible.
+ (cbranch<SHORT:mode>4): New expand rule.
+ (aarch64_cb<INT_CMP:code><GPI:mode>): New insn rule.
+ (aarch64_cb<INT_CMP:code><SHORT:mode>): Likewise.
+ * config/aarch64/constraints.md (Uc0): New constraint.
+ (Uc1): Likewise.
+ (Uc2): Likewise.
+ * config/aarch64/iterators.md (cmpbr_suffix): New mode attr.
+ (INT_CMP): New code iterator.
+ (cmpbr_imm_constraint): New code attr.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64-option-extensions.def (cmpbr): New
+ option.
+ * config/aarch64/aarch64.h (TARGET_CMPBR): New macro.
+ * doc/invoke.texi (cmpbr): New option.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64.md (far_branch): Replace 0/1 with
+ no/yes.
+ (aarch64_bcond): Handle rename.
+ (aarch64_cbz<optab><mode>1): Likewise.
+ (*aarch64_tbz<optab><mode>1): Likewise.
+ (@aarch64_tbz<optab><ALLI:mode><GPI:mode>): Likewise.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64.md (BRANCH_LEN_P_1MiB): New constant.
+ (BRANCH_LEN_N_1MiB): Likewise.
+ (BRANCH_LEN_P_32KiB): Likewise.
+ (BRANCH_LEN_N_32KiB): Likewise.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64.md (condjump): Rename to ...
+ (aarch64_bcond): ...here.
+ (*compare_condjump<GPI:mode>): Rename to ...
+ (*aarch64_bcond_wide_imm<GPI:mode>): ...here.
+ (aarch64_cb<optab><mode>): Rename to ...
+ (aarch64_cbz<optab><mode>1): ...here.
+ (*cb<optab><mode>1): Rename to ...
+ (*aarch64_tbz<optab><mode>1): ...here.
+ (@aarch64_tb<optab><ALLI:mode><GPI:mode>): Rename to ...
+ (@aarch64_tbz<optab><ALLI:mode><GPI:mode>): ...here.
+ (restore_stack_nonlocal): Handle rename.
+ (stack_protect_combined_test): Likewise.
+ * config/aarch64/aarch64-simd.md (cbranch<mode>4): Likewise.
+ * config/aarch64/aarch64-sme.md (aarch64_restore_za): Likewise.
+ * config/aarch64/aarch64.cc (aarch64_gen_test_and_branch): Likewise.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64.md (cbranch<mode>4): Reformat.
+ (cbranchcc4): Likewise.
+ (condjump): Likewise.
+ (*compare_condjump<GPI:mode>): Likewise.
+ (aarch64_cb<optab><mode>1): Likewise.
+ (*cb<optab><mode>1): Likewise.
+ (tbranch_<code><mode>3): Likewise.
+ (@aarch64_tb<optab><ALLI:mode><GPI:mode>): Likewise.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * config/aarch64/aarch64.md (condjump): Move.
+ (*compare_condjump<GPI:mode>): Likewise.
+ (aarch64_cb<optab><mode>1): Likewise.
+ (*cb<optab><mode>1): Likewise.
+ (tbranch_<code><mode>3): Likewise.
+ (@aarch64_tb<optab><ALLI:mode><GPI:mode>): Likewise.
+
+2025-07-03 Siddhesh Poyarekar <siddhesh@gotplt.org>
+
+ PR tree-optimization/120780
+ * tree-object-size.cc (inner_at_offset,
+ get_wholesize_for_memref): New functions.
+ (addr_object_size): Call get_wholesize_for_memref.
+
+2025-07-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/120936
+ * config/i386/i386.cc (x86_print_call_or_nop): Add a label
+ argument and use it to print label.
+ (x86_function_profiler): Emit label only when __mcount_loc
+ section is used.
+
+2025-07-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * auto-profile.cc (get_combined_location): Handle negative
+ offsets; output better diagnostics.
+ (get_relative_location_for_locus): Reutrn -1 for unknown location.
+ (function_instance::get_cgraph_node): New member function.
+ (match_with_target): New function.
+ (dump_stmt): New function.
+ (function_instance::lookup_count): New function.
+ (mark_expr_locations): New function.
+ (function_instance::match): New function.
+ (autofdo_source_profile::offline_external_functions): Do
+ not repeat renaming; manage two worklists and do matching.
+ (autofdo_source_profile::offline_unrealized_inlines): Simplify.
+ (afdo_set_bb_count): do not look for lost discriminators.
+ (auto_profile): Do not ICE when profile reading failed.
+ * common.opt (Wauto-profile): New warning flag
+ * doc/invoke.texi (-Wauto-profile): Document.
+
+2025-07-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-fnsummary.cc (analyze_function_body): For loop
+ heuristics use header count instead of preheader count.
+
+2025-07-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-cp.cc (update_profiling_info): Watch for division by zero.
+
+2025-07-03 Alex Coplan <alex.coplan@arm.com>
+
+ * config/aarch64/aarch64-sve.md
+ (vec_load_lanes<mode><vsingle>): Expand else operand in
+ subvector mode, as per optab documentation.
+ (vec_mask_load_lanes<mode><vsingle>): Add missing mode for
+ operand 3.
+ * config/aarch64/predicates.md (aarch64_maskload_else_operand):
+ Remove const_int.
+
+2025-07-03 Alex Coplan <alex.coplan@arm.com>
+
+ * doc/md.texi (Standard Names): Clarify mode of else operand for
+ vec_mask_load_lanesmn optab.
+
+2025-07-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-cp.cc (cs_interesting_for_ipcp_p): Handle
+ correctly GLOBAL0 afdo counts.
+ (ipcp_cloning_candidate_p): Do not rule out nodes
+ !node->optimize_for_size_p ().
+ (good_cloning_opportunity_p): Handle afdo counts
+ as non-zero.
+
+2025-07-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-cp.cc (hint_time_bonus): Return sreal and avoid
+ conversions to integer.
+ (good_cloning_opportunity_p): Avoid sreal to integer
+ conversions
+ (perform_estimation_of_a_value): Update.
+
+2025-07-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * auto-profile.cc (afdo_hot_bb_threshod): New global
+ variable.
+ (maybe_hot_afdo_count_p): New function.
+ (autofdo_source_profile::read): Do not set up dump file;
+ set afdo_hot_bb_threshod.
+ (afdo_annotate_cfg): Handle partial training.
+ (afdo_callsite_hot_enough_for_early_inline):
+ Use maybe_hot_afdo_count_p.
+ (auto_profile_offline::execute): Read autofdo file.
+ * auto-profile.h (maybe_hot_afdo_count_p): Declare.
+ (afdo_hot_bb_threshold): Declare.
+ * coverage.cc (read_counts_file): Also set gcov_profile_info.
+ (coverage_init): Do not read autofdo file.
+ * opts.cc (enable_fdo_optimizations): Add autofdo parameter;
+ do not set flag_branch_probabilities and flag_profile_values
+ with it.
+ (common_handle_option): Update.
+ * passes.cc (finish_optimization_passes): Do not end branch
+ prob here.
+ (pass_manager::dump_profile_report): Also mark change after
+ autofdo pass.
+ * profile.cc: Include auto-profile.h
+ (gcov_profile_info): New global variable.
+ (struct afdo_fdo_record): New struture.
+ (compute_branch_probabilities): Record afdo profile.
+ (end_branch_prob): Dump afdo/fdo profile comparsion.
+ * profile.h (gcov_profile_info): Declarre.
+ * tree-profile.cc (tree_profiling): Call end_branch_prob
+ (pass_ipa_tree_profile::gate): Also enable with autoFDO
+
+2025-07-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/118669
+ * tree-vect-stmts.cc (vectorizable_load): Emit loads
+ with proper (element) alignment.
+ (vectorizable_store): Likewise.
+
+2025-07-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/120908
+ * config/i386/i386.cc (legitimize_tls_address): Pass RDI to
+ gen_tls_local_dynamic_64.
+ * config/i386/i386.md (*tls_global_dynamic_64_largepic): Add
+ RDI clobber and use it to generate LEA.
+ (*tls_local_dynamic_64_<mode>): Likewise.
+ (*tls_local_dynamic_base_64_largepic): Likewise.
+ (@tls_local_dynamic_64_<mode>): Add a clobber.
+
2025-07-02 H.J. Lu <hjl.tools@gmail.com>
PR target/120908
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 6952979..f38cdfd 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250703
+20250704
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 8aaa006..e8cb92b 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,298 @@
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Makefile.in (gnatlib-sjlj): Delete.
+ (gnatlib-zcx): Do not modify Frontend_Exceptions constant.
+ * libgnat/system-linux-loongarch.ads (Frontend_Exceptions): Delete.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.cc (type_contains_only_integral_data): Do not
+ return false only because the type contains pointer data.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.cc (gnat_to_gnu_entity): Use default messages
+ for errors reported for Object_Size clauses.
+ (validate_size): Give an error for stand-alone objects of composite
+ types if the specified size is not a multiple of the alignment.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.cc (addressable_p): Add COMPG third parameter.
+ <COMPONENT_REF>: Do not return true out of alignment considerations
+ for non-strict-alignment targets if COMPG is set.
+ (Call_to_gnu): Pass true as COMPG in the call to the addressable_p
+ predicate if the called subprogram is an initialization procedure.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.cc (gnat_to_gnu) <N_Allocator>: Allocate the
+ bounds alongside the data if the Is_Constr_Array_Subt_With_Bounds
+ flag is set on the designated type.
+ <N_Free_Statement>: Take into account the allocated bounds if the
+ Is_Constr_Array_Subt_With_Bounds flag is set on the designated type.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.cc (gnat_to_gnu_component_type): Validate the
+ Component_Size like the size of a type only if the component type
+ is actually packed.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_elab.adb (Check_Overriding_Primitive): Find early call region
+ of the subprogram body declaration, not of the subprogram body stub.
+
+2025-07-03 Bob Duff <duff@adacore.com>
+
+ * gen_il-gen-gen_nodes.adb (N_Unchecked_Type_Conversion):
+ Remove useless Nmake_Assert.
+ * tbuild.adb (Unchecked_Convert_To):
+ Narrow the bitfield-related conditions.
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_util.adb (Insert_Actions): Fix check.
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_ch6.adb (Expand_Ctrl_Function_Call): Precisify comment.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch6.adb (Expand_Ctrl_Function_Call): Do not bail out for the
+ declarations of return objects.
+
+2025-07-03 Daniel King <dmking@adacore.com>
+
+ * Makefile.rtl (LIBGNAT_TARGET_PAIRS): New unit s-tsgsba__cheri.adb for morello-freebsd.
+ * libgnarl/s-tassta.adb (Get_Stack_Base): New function.
+ * libgnarl/s-tsgsba__cheri.adb: New file for CHERI targets.
+ * libgnarl/s-tsgsba.adb: New default file for non-CHERI targets.
+ * libgnat/s-stausa.adb (Fill_Stack, Compute_Result): Port to CHERI.
+ * libgnat/s-stausa.ads (Initialize_Analyzer, Stack_Analyzer): Port to CHERI.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Check_Return_Subtype_Indication): Use Original_Node.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Check_Return_Subtype_Indication): Use type from
+ explicit subtype indication, when possible.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Check_Return_Subtype_Indication): Adjust error message
+ to match the RM wording.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch3.adb (Check_Return_Subtype_Indication): Use the nominal
+ subtype of a return object; literally implement the RM rule about
+ elementary types; check for static subtype compatibility both when
+ the subtype is given as a subtype mark and a subtype indication.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * repinfo.adb (First_Comp_Or_Discr.Is_Placed_Before): Return True
+ only if the components are in the same component list.
+
+2025-07-03 Denis Mazzucato <mazzucato@adacore.com>
+
+ * sem_disp.adb (Check_Dispatching_call): Fix uninitialized Subp_Entity.
+ * sem_util.adb (Update_Controlling_Argument): No need to replace controlling argument
+ in case of functions.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * errid.ads: Adjust header to renaming and fix copyright line.
+ * errid.adb: Adjust header to renaming and add blank line.
+ * erroutc-pretty_emitter.ads: Adjust header to renaming.
+ * erroutc-pretty_emitter.adb: Likewise.
+ * erroutc-sarif_emitter.ads: Likewise.
+ * erroutc-sarif_emitter.adb: Likewise.
+ * errsw.ads: Adjust header to renaming and add blank line.
+ * errsw.adb: Likewise.
+ * json_utils.ads: Likewise.
+ * json_utils.adb: Adjust header to renaming.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * errid.ads (Diagnostic_Entries): Now a constant.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * errid.ads (Diagnostic_Entries): Remove nested aggregate.
+ * errsw.adb (Switches): Likewise.
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_ch7.adb (Make_Deep_Record_Body): Fix case of absent Initialize
+ primitive.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_ch3.adb (Count_Default_Sized_Task_Stacks): Refine subtypes of
+ parameters; same for callsites.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_imgv.adb (Expand_Value_Attribute): Do not call Set_Etype on N
+ after rewriting it by means of OK_Convert_To.
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_aggr.adb (Generate_Finalization_Actions): Stop assuming that
+ initialize primitive exists.
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_ch7.adb (Build_Record_Deep_Procs): Fix typo in comment.
+
+2025-07-03 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch12.adb (Install_Spec): Remove "not Is_Generic_Instance (Par)"
+ in test for setting Instance_Parent_Unit. Revise comment to no longer
+ say "noninstance", plus remove "???".
+ (Remove_Parent): Restructure if_statement to allow for both "elsif"
+ parts to be executed (by changing them to be separate if_statements
+ within an "else" part).
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_ch3.adb (Predefined_Primitive_Bodies): Fix comment.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_tss.adb (TSS): Refactor IF condition to make code smaller.
+ * lib.adb (Increment_Serial_Number, Synchronize_Serial_Number):
+ Use type of renamed object when creating renaming.
+ * lib.ads (Unit_Record): Refine subtype of dependency number.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valuef.adb: Document the prerequisites more precisely.
+ * libgnat/a-tifiio.adb (OK_Get_32): Adjust to the prerequisites.
+ (OK_Get_64): Likewise.
+ * libgnat/a-tifiio__128.adb (OK_Get_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Get_128): Likewise.
+ * libgnat/a-wtfiio.adb (OK_Get_32): Likewise.
+ (OK_Get_64): Likewise.
+ * libgnat/a-wtfiio__128.adb (OK_Get_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Get_128): Likewise.
+ * libgnat/a-ztfiio.adb (OK_Get_32): Likewise.
+ (OK_Get_64): Likewise.
+ * libgnat/a-ztfiio__128.adb (OK_Get_32): Likewise.
+ (OK_Get_64): Likewise.
+ (OK_Get_128): Likewise.
+ * exp_imgv.adb (Expand_Value_Attribute): Adjust the conditions under
+ which the RE_Value_Fixed{32,64,128} routines are called for ordinary
+ fixed-point types.
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_ch3.adb (Make_Predefined_Primitive_Specs): Fix comment.
+
+2025-07-03 Ronan Desplanques <desplanques@adacore.com>
+
+ * exp_ch7.adb (Insert_Actions_In_Scope_Around): Fix condition.
+
+2025-07-03 Bob Duff <duff@adacore.com>
+
+ * checks.adb: Remove unnecessary "return;" statements.
+ * eval_fat.adb: Likewise.
+ * exp_aggr.adb: Likewise.
+ * exp_attr.adb: Likewise.
+ * exp_ch3.adb: Likewise.
+ * exp_ch4.adb: Likewise.
+ * exp_ch5.adb: Likewise.
+ * exp_ch6.adb: Likewise.
+ * exp_unst.adb: Likewise.
+ * krunch.adb: Likewise.
+ * layout.adb: Likewise.
+ * libgnat/s-excdeb.adb: Likewise.
+ * libgnat/s-trasym__dwarf.adb: Likewise.
+ * par-endh.adb: Likewise.
+ * par-tchk.adb: Likewise.
+ * sem.adb: Likewise.
+ * sem_attr.adb: Likewise.
+ * sem_ch6.adb: Likewise.
+ * sem_elim.adb: Likewise.
+ * sem_eval.adb: Likewise.
+ * sfn_scan.adb: Likewise.
+
+2025-07-03 Bob Duff <duff@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_characteristics.rst:
+ Change Ignore to Disable.
+ * sem_ch13.ads (Analyze_Aspect_Specifications):
+ Minor: Remove incorrect comment; there is no need to check
+ Has_Aspects (N) at the call site.
+ * gnat_rm.texi: Regenerate.
+ * gnat_ugn.texi: Regenerate.
+
+2025-07-03 Bob Duff <duff@adacore.com>
+
+ * types.ads (Empty_Or_Error): Remove.
+ * atree.adb: Remove reference to Empty_Or_Error.
+ * par-endh.adb: Likewise.
+ * sem_ch12.adb: Likewise.
+ * sem_ch3.adb: Likewise.
+ * sem_util.adb: Likewise.
+ * treepr.adb: Likewise.
+
+2025-07-03 Viljar Indus <indus@adacore.com>
+
+ * sem_ch10.adb(Analyze_With_Clause): Call Semantics instead
+ of Analyze to bring Current_Sem_Unit up to date.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * lib-xref-spark_specific.adb
+ (Enclosing_Subprogram_Or_Library_Package): Traverse subunits and body
+ stubs.
+
+2025-07-03 Tonu Naks <naks@adacore.com>
+
+ * libgnat/i-cstrin.ads (Value): add documentation
+
+2025-07-03 Aleksandra Pasek <pasek@adacore.com>
+
+ * libgnat/a-strsup.adb (Super_Delete): Fix index check.
+ * libgnat/a-stwisu.adb (Super_Delete): Likewise.
+ * libgnat/a-stzsup.adb (Super_Delete): Likewise.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch4.adb (Handle_Changed_Representation): Alphabetize local
+ variables. Set the No_Finalize_Actions flag on the assignment.
+
+2025-07-03 Joffrey Huguet <huguet@adacore.com>
+
+ * aspects.ads: Define an identifier for Potentially_Invalid.
+ * doc/gnat_rm/implementation_defined_aspects.rst: Add section for Potentially_Invalid.
+ * sem_attr.adb (Analyze_Attribute_Old_Result): Attribute Old is allowed to occur in a
+ Potentially_Invalid aspect.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Handle Potentially_Invalid.
+ * sem_util.adb (Has_Potentially_Invalid): Returns True iff an entity is subject to the
+ Potentially_Invalid aspect.
+ * sem_util.ads (Has_Potentially_Invalid): Idem.
+ * snames.ads-tmpl: New name for Potentially_Invalid.
+ * gnat_rm.texi: Regenerate.
+
+2025-07-03 Piotr Trojanek <trojanek@adacore.com>
+
+ * sem_ch10.adb (Analyze_Compilation_Unit): Ignored ghost unit need no
+ elaboration checks.
+
+2025-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * libgnat/s-valued.adb (Integer_to_Decimal): Use truncation for the
+ scaled divide operation performed for bases other than 10.
+
2025-07-01 Eric Botcazou <ebotcazou@adacore.com>
PR ada/120705
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 3557b46..8615b59 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -840,35 +840,6 @@ gnatlib-shared:
PICFLAG_FOR_TARGET="$(PICFLAG_FOR_TARGET)" \
$(GNATLIB_SHARED)
-# When building a SJLJ runtime for VxWorks, we need to ensure that the extra
-# linker options needed for ZCX are not passed to prevent the inclusion of
-# useless objects and potential troubles from the presence of extra symbols
-# and references in some configurations. The inhibition is performed by
-# commenting the pragma instead of deleting the line, as the latter might
-# result in getting multiple blank lines, hence possible style check errors.
-gnatlib-sjlj:
- $(MAKE) $(FLAGS_TO_PASS) \
- EH_MECHANISM="" \
- MULTISUBDIR="$(MULTISUBDIR)" \
- THREAD_KIND="$(THREAD_KIND)" \
- LN_S="$(LN_S)" \
- ../stamp-gnatlib1-$(RTSDIR)
- sed \
- -e 's/Frontend_Exceptions.*/Frontend_Exceptions : constant Boolean := True;/' \
- -e 's/ZCX_By_Default.*/ZCX_By_Default : constant Boolean := False;/' \
- $(RTSDIR)/system.ads > $(RTSDIR)/s.ads
- $(MV) $(RTSDIR)/s.ads $(RTSDIR)/system.ads
- $(MAKE) $(FLAGS_TO_PASS) \
- EH_MECHANISM="" \
- GNATLIBFLAGS="$(GNATLIBFLAGS)" \
- GNATLIBCFLAGS="$(GNATLIBCFLAGS)" \
- GNATLIBCFLAGS_FOR_C="$(GNATLIBCFLAGS_FOR_C)" \
- FORCE_DEBUG_ADAFLAGS="$(FORCE_DEBUG_ADAFLAGS)" \
- MULTISUBDIR="$(MULTISUBDIR)" \
- THREAD_KIND="$(THREAD_KIND)" \
- LN_S="$(LN_S)" \
- gnatlib
-
gnatlib-zcx:
$(MAKE) $(FLAGS_TO_PASS) \
EH_MECHANISM="-gcc" \
@@ -877,7 +848,6 @@ gnatlib-zcx:
LN_S="$(LN_S)" \
../stamp-gnatlib1-$(RTSDIR)
sed \
- -e 's/Frontend_Exceptions.*/Frontend_Exceptions : constant Boolean := False;/' \
-e 's/ZCX_By_Default.*/ZCX_By_Default : constant Boolean := True;/' \
$(RTSDIR)/system.ads > $(RTSDIR)/s.ads
$(MV) $(RTSDIR)/s.ads $(RTSDIR)/system.ads
diff --git a/gcc/ada/libgnat/system-linux-loongarch.ads b/gcc/ada/libgnat/system-linux-loongarch.ads
index 77a2139..683b7a4 100644
--- a/gcc/ada/libgnat/system-linux-loongarch.ads
+++ b/gcc/ada/libgnat/system-linux-loongarch.ads
@@ -139,7 +139,6 @@ private
Always_Compatible_Rep : constant Boolean := False;
Suppress_Standard_Library : constant Boolean := False;
Use_Ada_Main_Program_Name : constant Boolean := False;
- Frontend_Exceptions : constant Boolean := False;
ZCX_By_Default : constant Boolean := True;
end System;
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 9d69298..362dc50 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -3438,20 +3438,41 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
an overflow error if the constant is negative but INTOP is not. */
&& (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (intop))
|| (TYPE_PRECISION (TREE_TYPE (intop))
- == TYPE_PRECISION (TREE_TYPE (ptrop)))))
- {
- enum tree_code subcode = resultcode;
- tree int_type = TREE_TYPE (intop);
- if (TREE_CODE (intop) == MINUS_EXPR)
- subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
- /* Convert both subexpression types to the type of intop,
- because weird cases involving pointer arithmetic
- can result in a sum or difference with different type args. */
- ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)),
- subcode, ptrop,
- convert (int_type, TREE_OPERAND (intop, 1)),
- true);
- intop = convert (int_type, TREE_OPERAND (intop, 0));
+ == TYPE_PRECISION (TREE_TYPE (ptrop))))
+ && TYPE_PRECISION (TREE_TYPE (intop)) <= TYPE_PRECISION (sizetype))
+ {
+ tree intop0 = TREE_OPERAND (intop, 0);
+ tree intop1 = TREE_OPERAND (intop, 1);
+ if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
+ || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
+ {
+ tree optype = c_common_type_for_size (TYPE_PRECISION (sizetype),
+ TYPE_UNSIGNED (sizetype));
+ intop0 = convert (optype, intop0);
+ intop1 = convert (optype, intop1);
+ }
+ tree t = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (intop0), intop0,
+ convert (TREE_TYPE (intop0), size_exp));
+ intop0 = convert (sizetype, t);
+ if (TREE_OVERFLOW_P (intop0) && !TREE_OVERFLOW (t))
+ intop0 = wide_int_to_tree (TREE_TYPE (intop0), wi::to_wide (intop0));
+ t = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (intop1), intop1,
+ convert (TREE_TYPE (intop1), size_exp));
+ intop1 = convert (sizetype, t);
+ if (TREE_OVERFLOW_P (intop1) && !TREE_OVERFLOW (t))
+ intop1 = wide_int_to_tree (TREE_TYPE (intop1), wi::to_wide (intop1));
+ intop = build_binary_op (EXPR_LOCATION (intop), TREE_CODE (intop),
+ intop0, intop1, true);
+
+ /* Create the sum or difference. */
+ if (resultcode == MINUS_EXPR)
+ intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop);
+
+ ret = fold_build_pointer_plus_loc (loc, ptrop, intop);
+
+ fold_undefer_and_ignore_overflow_warnings ();
+
+ return ret;
}
/* Convert the integer argument to a type the same size as sizetype
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index dbbb021..1c3e697 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -249,6 +249,8 @@ AARCH64_OPT_EXTENSION("mops", MOPS, (), (), (), "mops")
AARCH64_OPT_EXTENSION("cssc", CSSC, (), (), (), "cssc")
+AARCH64_OPT_EXTENSION("cmpbr", CMPBR, (), (), (), "cmpbr")
+
AARCH64_OPT_EXTENSION("lse128", LSE128, (LSE), (), (), "lse128")
AARCH64_OPT_EXTENSION("d128", D128, (LSE128), (), (), "d128")
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 31f2f5b..e946e8d 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -1135,6 +1135,8 @@ bool aarch64_general_check_builtin_call (location_t, vec<location_t>,
unsigned int, tree, unsigned int,
tree *);
+bool aarch64_cb_rhs (rtx_code op_code, rtx rhs);
+
namespace aarch64 {
void report_non_ice (location_t, tree, unsigned int);
void report_out_of_range (location_t, tree, unsigned int, HOST_WIDE_INT,
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index af574d5..8de79ca 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3966,7 +3966,7 @@
rtx cc_reg = aarch64_gen_compare_reg (code, val, const0_rtx);
rtx cmp_rtx = gen_rtx_fmt_ee (code, DImode, cc_reg, const0_rtx);
- emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[3]));
+ emit_jump_insn (gen_aarch64_bcond (cmp_rtx, cc_reg, operands[3]));
DONE;
})
diff --git a/gcc/config/aarch64/aarch64-sme.md b/gcc/config/aarch64/aarch64-sme.md
index f7958c9..b8bb4cc 100644
--- a/gcc/config/aarch64/aarch64-sme.md
+++ b/gcc/config/aarch64/aarch64-sme.md
@@ -391,7 +391,7 @@
auto label = gen_label_rtx ();
auto tpidr2 = gen_rtx_REG (DImode, R16_REGNUM);
emit_insn (gen_aarch64_read_tpidr2 (tpidr2));
- auto jump = emit_likely_jump_insn (gen_aarch64_cbnedi1 (tpidr2, label));
+ auto jump = emit_likely_jump_insn (gen_aarch64_cbznedi1 (tpidr2, label));
JUMP_LABEL (jump) = label;
aarch64_restore_za (operands[0]);
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index abbb977..f3ce3a1 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -959,6 +959,39 @@ svpattern_token (enum aarch64_svpattern pattern)
gcc_unreachable ();
}
+/* Return true if RHS is an operand suitable for a CB<cc> (immediate)
+ instruction. OP_CODE determines the type of the comparison. */
+bool
+aarch64_cb_rhs (rtx_code op_code, rtx rhs)
+{
+ if (!CONST_INT_P (rhs))
+ return REG_P (rhs);
+
+ HOST_WIDE_INT rhs_val = INTVAL (rhs);
+
+ switch (op_code)
+ {
+ case EQ:
+ case NE:
+ case GT:
+ case GTU:
+ case LT:
+ case LTU:
+ return IN_RANGE (rhs_val, 0, 63);
+
+ case GE: /* CBGE: signed greater than or equal */
+ case GEU: /* CBHS: unsigned greater than or equal */
+ return IN_RANGE (rhs_val, 1, 64);
+
+ case LE: /* CBLE: signed less than or equal */
+ case LEU: /* CBLS: unsigned less than or equal */
+ return IN_RANGE (rhs_val, -1, 62);
+
+ default:
+ return false;
+ }
+}
+
/* Return the location of a piece that is known to be passed or returned
in registers. FIRST_ZR is the first unused vector argument register
and FIRST_PR is the first unused predicate argument register. */
@@ -2884,10 +2917,10 @@ aarch64_gen_test_and_branch (rtx_code code, rtx x, int bitnum,
emit_insn (gen_aarch64_and3nr_compare0 (mode, x, mask));
rtx cc_reg = gen_rtx_REG (CC_NZVmode, CC_REGNUM);
rtx x = gen_rtx_fmt_ee (code, CC_NZVmode, cc_reg, const0_rtx);
- return gen_condjump (x, cc_reg, label);
+ return gen_aarch64_bcond (x, cc_reg, label);
}
- return gen_aarch64_tb (code, mode, mode,
- x, gen_int_mode (bitnum, mode), label);
+ return gen_aarch64_tbz (code, mode, mode,
+ x, gen_int_mode (bitnum, mode), label);
}
/* Consider the operation:
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index e8bd8c7..d5c4a42 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -410,6 +410,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE ATTRIBUTE_UNUSED
/* CSSC instructions are enabled through +cssc. */
#define TARGET_CSSC AARCH64_HAVE_ISA (CSSC)
+/* CB<cc> instructions are enabled through +cmpbr. */
+#define TARGET_CMPBR AARCH64_HAVE_ISA (CMPBR)
+
/* Make sure this is always defined so we don't have to check for ifdefs
but rather use normal ifs. */
#ifndef TARGET_FIX_ERR_A53_835769_DEFAULT
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index e11e130..509ef4c 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -569,9 +569,7 @@
;; Attribute that specifies whether we are dealing with a branch to a
;; label that is far away, i.e. further away than the maximum/minimum
;; representable in a signed 21-bits number.
-;; 0 :=: no
-;; 1 :=: yes
-(define_attr "far_branch" "" (const_int 0))
+(define_attr "far_branch" "no,yes" (const_string "no"))
;; Attribute that specifies whether the alternative uses MOVPRFX.
(define_attr "movprfx" "no,yes" (const_string "no"))
@@ -682,6 +680,10 @@
"msrr\t%x0, %x1, %H1"
)
+;; -------------------------------------------------------------------
+;; Unconditional jumps
+;; -------------------------------------------------------------------
+
(define_insn "indirect_jump"
[(set (pc) (match_operand:DI 0 "register_operand" "r"))]
""
@@ -700,18 +702,70 @@
[(set_attr "type" "branch")]
)
-(define_expand "cbranch<mode>4"
+;; Maximum PC-relative positive/negative displacements for various branching
+;; instructions.
+(define_constants
+ [
+ ;; +/- 1MiB. Used by B.<cond>, CBZ, CBNZ.
+ (BRANCH_LEN_P_1MiB 1048572)
+ (BRANCH_LEN_N_1MiB -1048576)
+
+ ;; +/- 32KiB. Used by TBZ, TBNZ.
+ (BRANCH_LEN_P_32KiB 32764)
+ (BRANCH_LEN_N_32KiB -32768)
+
+ ;; +/- 1KiB. Used by CBB<cond>, CBH<cond>, CB<cond>.
+ (BRANCH_LEN_P_1Kib 1020)
+ (BRANCH_LEN_N_1Kib -1024)
+ ]
+)
+
+;; -------------------------------------------------------------------
+;; Conditional jumps
+;; -------------------------------------------------------------------
+
+;; The order of the rules below is important.
+;; Higher priority rules are preferred because they can express larger
+;; displacements.
+;; 1) EQ/NE comparisons against zero are handled by CBZ/CBNZ.
+;; 2) LT/GE comparisons against zero are handled by TBZ/TBNZ.
+;; 3) When the CMPBR extension is enabled:
+;; a) Comparisons between two registers are handled by
+;; CBB<cond>/CBH<cond>/CB<cond>.
+;; b) Comparisons between a GP register and an in range immediate are
+;; handled by CB<cond> (immediate).
+;; 4) Otherwise, emit a CMP+B<cond> sequence.
+;; -------------------------------------------------------------------
+
+(define_expand "cbranch<GPI:mode>4"
[(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
[(match_operand:GPI 1 "register_operand")
(match_operand:GPI 2 "aarch64_plus_operand")])
- (label_ref (match_operand 3 "" ""))
+ (label_ref (match_operand 3))
(pc)))]
""
- "
- operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
- operands[2]);
- operands[2] = const0_rtx;
- "
+ {
+ if (TARGET_CMPBR && aarch64_cb_rhs (GET_CODE (operands[0]), operands[2]))
+ {
+ /* The branch is supported natively. */
+ }
+ else
+ {
+ operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ operands[2] = const0_rtx;
+ }
+ }
+)
+
+(define_expand "cbranch<SHORT:mode>4"
+ [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
+ [(match_operand:SHORT 1 "register_operand")
+ (match_operand:SHORT 2 "aarch64_reg_or_zero")])
+ (label_ref (match_operand 3))
+ (pc)))]
+ "TARGET_CMPBR"
+ ""
)
(define_expand "cbranch<mode>4"
@@ -719,25 +773,301 @@
(match_operator 0 "aarch64_comparison_operator"
[(match_operand:GPF_F16 1 "register_operand")
(match_operand:GPF_F16 2 "aarch64_fp_compare_operand")])
- (label_ref (match_operand 3 "" ""))
+ (label_ref (match_operand 3))
(pc)))]
""
- "
- operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
- operands[2]);
- operands[2] = const0_rtx;
- "
+ {
+ operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
+ operands[2]);
+ operands[2] = const0_rtx;
+ }
)
(define_expand "cbranchcc4"
- [(set (pc) (if_then_else
- (match_operator 0 "aarch64_comparison_operator"
- [(match_operand 1 "cc_register")
- (match_operand 2 "const0_operand")])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
+ [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
+ [(match_operand 1 "cc_register")
+ (match_operand 2 "const0_operand")])
+ (label_ref (match_operand 3))
+ (pc)))]
""
- "")
+ ""
+)
+
+;; For an EQ/NE comparison against zero, emit `CBZ`/`CBNZ`
+(define_insn "aarch64_cbz<optab><mode>1"
+ [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
+ (const_int 0))
+ (label_ref (match_operand 1))
+ (pc)))]
+ "!aarch64_track_speculation"
+ {
+ if (get_attr_length (insn) == 8)
+ return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
+ else
+ return "<cbz>\\t%<w>0, %l1";
+ }
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 1) (pc))
+ (const_int BRANCH_LEN_N_1MiB))
+ (lt (minus (match_dup 1) (pc))
+ (const_int BRANCH_LEN_P_1MiB)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_branch")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1MiB))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1MiB)))
+ (const_string "no")
+ (const_string "yes")))]
+)
+
+;; For an LT/GE comparison against zero, emit `TBZ`/`TBNZ`
+(define_insn "*aarch64_tbz<optab><mode>1"
+ [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
+ (const_int 0))
+ (label_ref (match_operand 1))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "!aarch64_track_speculation"
+ {
+ if (get_attr_length (insn) == 8)
+ {
+ if (get_attr_far_branch (insn) == FAR_BRANCH_YES)
+ return aarch64_gen_far_branch (operands, 1, "Ltb",
+ "<inv_tb>\\t%<w>0, <sizem1>, ");
+ else
+ {
+ char buf[64];
+ uint64_t val = ((uint64_t) 1)
+ << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
+ sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
+ output_asm_insn (buf, operands);
+ return "<bcond>\t%l1";
+ }
+ }
+ else
+ return "<tbz>\t%<w>0, <sizem1>, %l1";
+ }
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 1) (pc))
+ (const_int BRANCH_LEN_N_32KiB))
+ (lt (minus (match_dup 1) (pc))
+ (const_int BRANCH_LEN_P_32KiB)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_branch")
+ (if_then_else (and (ge (minus (match_dup 1) (pc))
+ (const_int BRANCH_LEN_N_1MiB))
+ (lt (minus (match_dup 1) (pc))
+ (const_int BRANCH_LEN_P_1MiB)))
+ (const_string "no")
+ (const_string "yes")))]
+)
+
+;; Emit a `CB<cond> (register)` or `CB<cond> (immediate)` instruction.
+;; The immediate range depends on the comparison code.
+;; Comparisons against immediates outside this range fall back to
+;; CMP + B<cond>.
+(define_insn "aarch64_cb<INT_CMP:code><GPI:mode>"
+ [(set (pc) (if_then_else (INT_CMP
+ (match_operand:GPI 0 "register_operand" "r")
+ (match_operand:GPI 1 "nonmemory_operand"
+ "r<INT_CMP:cmpbr_imm_constraint>"))
+ (label_ref (match_operand 2))
+ (pc)))]
+ "TARGET_CMPBR && aarch64_cb_rhs (<INT_CMP:CODE>, operands[1])"
+ {
+ return (get_attr_far_branch (insn) == FAR_BRANCH_NO)
+ ? "cb<INT_CMP:cmp_op>\\t%<w>0, %<w>1, %l2"
+ : aarch64_gen_far_branch (operands, 2, "L",
+ "cb<INT_CMP:inv_cmp_op>\\t%<w>0, %<w>1, ");
+ }
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1Kib))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1Kib)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_branch")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1Kib))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1Kib)))
+ (const_string "no")
+ (const_string "yes")))]
+)
+
+;; Emit a `CBB<cond> (register)` or `CBH<cond> (register)` instruction.
+(define_insn "aarch64_cb<INT_CMP:code><SHORT:mode>"
+ [(set (pc) (if_then_else (INT_CMP
+ (match_operand:SHORT 0 "register_operand" "r")
+ (match_operand:SHORT 1 "aarch64_reg_or_zero" "rZ"))
+ (label_ref (match_operand 2))
+ (pc)))]
+ "TARGET_CMPBR"
+ {
+ return (get_attr_far_branch (insn) == FAR_BRANCH_NO)
+ ? "cb<SHORT:cmpbr_suffix><INT_CMP:cmp_op>\\t%<w>0, %<w>1, %l2"
+ : aarch64_gen_far_branch (operands, 2, "L",
+ "cb<SHORT:cmpbr_suffix><INT_CMP:inv_cmp_op>\\t%<w>0, %<w>1, ");
+ }
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1Kib))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1Kib)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_branch")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1Kib))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1Kib)))
+ (const_string "no")
+ (const_string "yes")))]
+)
+
+;; Emit `B<cond>`, assuming that the condition is already in the CC register.
+(define_insn "aarch64_bcond"
+ [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
+ [(match_operand 1 "cc_register")
+ (const_int 0)])
+ (label_ref (match_operand 2))
+ (pc)))]
+ ""
+ {
+ /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
+ but the "." is required for SVE conditions. */
+ bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
+ if (get_attr_length (insn) == 8)
+ return aarch64_gen_far_branch (operands, 2, "Lbcond",
+ use_dot_p ? "b.%M0\\t" : "b%M0\\t");
+ else
+ return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
+ }
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1MiB))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1MiB)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_branch")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1MiB))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1MiB)))
+ (const_string "no")
+ (const_string "yes")))]
+)
+
+;; For a 24-bit immediate CST we can optimize the compare for equality
+;; and branch sequence from:
+;; mov x0, #imm1
+;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
+;; cmp x1, x0
+;; b<ne,eq> .Label
+;; into the shorter:
+;; sub x0, x1, #(CST & 0xfff000)
+;; subs x0, x0, #(CST & 0x000fff)
+;; b<ne,eq> .Label
+(define_insn_and_split "*aarch64_bcond_wide_imm<GPI:mode>"
+ [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
+ (match_operand:GPI 1 "aarch64_imm24" "n"))
+ (label_ref:P (match_operand 2))
+ (pc)))]
+ "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
+ && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
+ && !reload_completed"
+ "#"
+ "&& true"
+ [(const_int 0)]
+ {
+ HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
+ HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
+ rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
+ emit_insn (gen_add<GPI:mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
+ emit_insn (gen_add<GPI:mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
+ rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
+ rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
+ cc_reg, const0_rtx);
+ emit_jump_insn (gen_aarch64_bcond (cmp_rtx, cc_reg, operands[2]));
+ DONE;
+ }
+)
+
+;; -------------------------------------------------------------------
+;; Test bit and branch
+;; -------------------------------------------------------------------
+
+(define_expand "tbranch_<code><mode>3"
+ [(set (pc) (if_then_else (EQL
+ (match_operand:SHORT 0 "register_operand")
+ (match_operand 1 "const0_operand"))
+ (label_ref (match_operand 2 ""))
+ (pc)))]
+ ""
+{
+ rtx bitvalue = gen_reg_rtx (<ZEROM>mode);
+ rtx reg = gen_lowpart (<ZEROM>mode, operands[0]);
+ rtx val = gen_int_mode (HOST_WIDE_INT_1U << UINTVAL (operands[1]),
+ <MODE>mode);
+ emit_insn (gen_and<zerom>3 (bitvalue, reg, val));
+ operands[1] = const0_rtx;
+ operands[0] = aarch64_gen_compare_reg (<CODE>, bitvalue,
+ operands[1]);
+})
+
+(define_insn "@aarch64_tbz<optab><ALLI:mode><GPI:mode>"
+ [(set (pc) (if_then_else (EQL
+ (zero_extract:GPI
+ (match_operand:ALLI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand 1 "aarch64_simd_shift_imm_<ALLI:mode>" "n"))
+ (const_int 0))
+ (label_ref (match_operand 2))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "!aarch64_track_speculation"
+ {
+ if (get_attr_length (insn) == 8)
+ {
+ if (get_attr_far_branch (insn) == 1)
+ return aarch64_gen_far_branch (operands, 2, "Ltb",
+ "<inv_tb>\\t%<ALLI:w>0, %1, ");
+ else
+ {
+ operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
+ return "tst\t%<ALLI:w>0, %1\;<bcond>\t%l2";
+ }
+ }
+ else
+ return "<tbz>\t%<ALLI:w>0, %1, %l2";
+ }
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_32KiB))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_32KiB)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_branch")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1MiB))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1MiB)))
+ (const_string "no")
+ (const_string "yes")))]
+
+)
(define_insn "@ccmp<CC_ONLY:mode><GPI:mode>"
[(set (match_operand:CC_ONLY 1 "cc_register")
@@ -869,71 +1199,6 @@
}
)
-(define_insn "condjump"
- [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
- [(match_operand 1 "cc_register" "") (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- ""
- {
- /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
- but the "." is required for SVE conditions. */
- bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
- if (get_attr_length (insn) == 8)
- return aarch64_gen_far_branch (operands, 2, "Lbcond",
- use_dot_p ? "b.%M0\\t" : "b%M0\\t");
- else
- return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
- }
- [(set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
- (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
- (const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
- (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
-)
-
-;; For a 24-bit immediate CST we can optimize the compare for equality
-;; and branch sequence from:
-;; mov x0, #imm1
-;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
-;; cmp x1, x0
-;; b<ne,eq> .Label
-;; into the shorter:
-;; sub x0, x1, #(CST & 0xfff000)
-;; subs x0, x0, #(CST & 0x000fff)
-;; b<ne,eq> .Label
-(define_insn_and_split "*compare_condjump<GPI:mode>"
- [(set (pc) (if_then_else (EQL
- (match_operand:GPI 0 "register_operand" "r")
- (match_operand:GPI 1 "aarch64_imm24" "n"))
- (label_ref:P (match_operand 2 "" ""))
- (pc)))]
- "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
- && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
- && !reload_completed"
- "#"
- "&& true"
- [(const_int 0)]
- {
- HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
- HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
- rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
- emit_insn (gen_add<GPI:mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
- emit_insn (gen_add<GPI:mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
- rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
- rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
- cc_reg, const0_rtx);
- emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
- DONE;
- }
-)
-
(define_expand "casesi"
[(match_operand:SI 0 "register_operand") ; Index
(match_operand:SI 1 "const_int_operand") ; Lower bound
@@ -1125,127 +1390,6 @@
(set_attr "sls_length" "retbr")]
)
-(define_insn "aarch64_cb<optab><mode>1"
- [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "!aarch64_track_speculation"
- {
- if (get_attr_length (insn) == 8)
- return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
- else
- return "<cbz>\\t%<w>0, %l1";
- }
- [(set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
- (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
- (const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
- (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
-)
-
-(define_expand "tbranch_<code><mode>3"
- [(set (pc) (if_then_else
- (EQL (match_operand:SHORT 0 "register_operand")
- (match_operand 1 "const0_operand"))
- (label_ref (match_operand 2 ""))
- (pc)))]
- ""
-{
- rtx bitvalue = gen_reg_rtx (<ZEROM>mode);
- rtx reg = gen_lowpart (<ZEROM>mode, operands[0]);
- rtx val = gen_int_mode (HOST_WIDE_INT_1U << UINTVAL (operands[1]), <MODE>mode);
- emit_insn (gen_and<zerom>3 (bitvalue, reg, val));
- operands[1] = const0_rtx;
- operands[0] = aarch64_gen_compare_reg (<CODE>, bitvalue,
- operands[1]);
-})
-
-(define_insn "@aarch64_tb<optab><ALLI:mode><GPI:mode>"
- [(set (pc) (if_then_else
- (EQL (zero_extract:GPI (match_operand:ALLI 0 "register_operand" "r")
- (const_int 1)
- (match_operand 1
- "aarch64_simd_shift_imm_<ALLI:mode>" "n"))
- (const_int 0))
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (clobber (reg:CC CC_REGNUM))]
- "!aarch64_track_speculation"
- {
- if (get_attr_length (insn) == 8)
- {
- if (get_attr_far_branch (insn) == 1)
- return aarch64_gen_far_branch (operands, 2, "Ltb",
- "<inv_tb>\\t%<ALLI:w>0, %1, ");
- else
- {
- operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
- return "tst\t%<ALLI:w>0, %1\;<bcond>\t%l2";
- }
- }
- else
- return "<tbz>\t%<ALLI:w>0, %1, %l2";
- }
- [(set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
- (lt (minus (match_dup 2) (pc)) (const_int 32764)))
- (const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
- (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
-
-)
-
-(define_insn "*cb<optab><mode>1"
- [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (clobber (reg:CC CC_REGNUM))]
- "!aarch64_track_speculation"
- {
- if (get_attr_length (insn) == 8)
- {
- if (get_attr_far_branch (insn) == 1)
- return aarch64_gen_far_branch (operands, 1, "Ltb",
- "<inv_tb>\\t%<w>0, <sizem1>, ");
- else
- {
- char buf[64];
- uint64_t val = ((uint64_t) 1)
- << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
- sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
- output_asm_insn (buf, operands);
- return "<bcond>\t%l1";
- }
- }
- else
- return "<tbz>\t%<w>0, <sizem1>, %l1";
- }
- [(set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
- (lt (minus (match_dup 1) (pc)) (const_int 32764)))
- (const_int 4)
- (const_int 8)))
- (set (attr "far_branch")
- (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
- (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
- (const_int 0)
- (const_int 1)))]
-)
-
(define_expand "save_stack_nonlocal"
[(set (match_operand 0 "memory_operand")
(match_operand 1 "register_operand"))]
@@ -1316,13 +1460,13 @@
emit_insn (gen_subdi3_compare1 (gcs_now, gcs_old, gcs_now));
rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
rtx cmp_rtx = gen_rtx_fmt_ee (EQ, DImode, cc_reg, const0_rtx);
- emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, done_label));
+ emit_jump_insn (gen_aarch64_bcond (cmp_rtx, cc_reg, done_label));
emit_label (loop_label);
emit_insn (gen_aarch64_gcspopm_xzr ());
emit_insn (gen_adddi3_compare0 (gcs_now, gcs_now, GEN_INT (-8)));
cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
cmp_rtx = gen_rtx_fmt_ee (NE, DImode, cc_reg, const0_rtx);
- emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, loop_label));
+ emit_jump_insn (gen_aarch64_bcond (cmp_rtx, cc_reg, loop_label));
emit_label (done_label);
}
DONE;
@@ -8090,8 +8234,8 @@
: gen_stack_protect_test_si) (operands[0], operands[1]));
rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
- emit_jump_insn (gen_condjump (gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx),
- cc_reg, operands[2]));
+ emit_jump_insn (gen_aarch64_bcond (gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx),
+ cc_reg, operands[2]));
DONE;
})
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index e9f69f8..dc1925d 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -304,6 +304,24 @@
(and (match_code "const_int")
(match_test "(unsigned HOST_WIDE_INT) ival <= 7")))
+(define_constraint "Uc0"
+ "@internal
+ A constraint that matches the integers 0...63."
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, 0, 63)")))
+
+(define_constraint "Uc1"
+ "@internal
+ A constraint that matches the integers 1...64."
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, 1, 64)")))
+
+(define_constraint "Uc2"
+ "@internal
+ A constraint that matches the integers -1...62."
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, -1, 62)")))
+
(define_constraint "Up3"
"@internal
A constraint that matches the integers 2^(0...4)."
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index a8957681..c59fcd6 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -2961,6 +2961,36 @@
(geu "hs")
(gtu "hi")])
+(define_code_attr inv_cmp_op [(lt "ge")
+ (le "gt")
+ (eq "ne")
+ (ne "eq")
+ (ge "lt")
+ (gt "le")
+ (ltu "hs")
+ (leu "hi")
+ (geu "lo")
+ (gtu "ls")])
+
+(define_mode_attr cmpbr_suffix [(QI "b") (HI "h")])
+
+(define_code_iterator INT_CMP [lt le eq ne ge gt ltu leu geu gtu])
+
+(define_code_attr cmpbr_imm_constraint [
+ (eq "Uc0")
+ (ne "Uc0")
+ (gt "Uc0")
+ (gtu "Uc0")
+ (lt "Uc0")
+ (ltu "Uc0")
+
+ (ge "Uc1")
+ (geu "Uc1")
+
+ (le "Uc2")
+ (leu "Uc2")
+])
+
(define_code_attr fix_trunc_optab [(fix "fix_trunc")
(unsigned_fix "fixuns_trunc")])
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 24aedc1..b64175d 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -23686,19 +23686,21 @@ x86_field_alignment (tree type, int computed)
/* Print call to TARGET to FILE. */
static void
-x86_print_call_or_nop (FILE *file, const char *target)
+x86_print_call_or_nop (FILE *file, const char *target,
+ const char *label)
{
if (flag_nop_mcount || !strcmp (target, "nop"))
/* 5 byte nop: nopl 0(%[re]ax,%[re]ax,1) */
- fprintf (file, "1:" ASM_BYTE "0x0f, 0x1f, 0x44, 0x00, 0x00\n");
+ fprintf (file, "%s" ASM_BYTE "0x0f, 0x1f, 0x44, 0x00, 0x00\n",
+ label);
else if (!TARGET_PECOFF && flag_pic)
{
gcc_assert (flag_plt);
- fprintf (file, "1:\tcall\t%s@PLT\n", target);
+ fprintf (file, "%s\tcall\t%s@PLT\n", label, target);
}
else
- fprintf (file, "1:\tcall\t%s\n", target);
+ fprintf (file, "%s\tcall\t%s\n", label, target);
}
static bool
@@ -23783,6 +23785,13 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
const char *mcount_name = MCOUNT_NAME;
+ bool fentry_section_p
+ = (flag_record_mcount
+ || lookup_attribute ("fentry_section",
+ DECL_ATTRIBUTES (current_function_decl)));
+
+ const char *label = fentry_section_p ? "1:" : "";
+
if (current_fentry_name (&mcount_name))
;
else if (fentry_name)
@@ -23818,11 +23827,12 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
reg = legacy_reg;
}
if (ASSEMBLER_DIALECT == ASM_INTEL)
- fprintf (file, "1:\tmovabs\t%s, OFFSET FLAT:%s\n"
- "\tcall\t%s\n", reg, mcount_name, reg);
+ fprintf (file, "%s\tmovabs\t%s, OFFSET FLAT:%s\n"
+ "\tcall\t%s\n", label, reg, mcount_name,
+ reg);
else
- fprintf (file, "1:\tmovabsq\t$%s, %%%s\n\tcall\t*%%%s\n",
- mcount_name, reg, reg);
+ fprintf (file, "%s\tmovabsq\t$%s, %%%s\n\tcall\t*%%%s\n",
+ label, mcount_name, reg, reg);
break;
case CM_LARGE_PIC:
#ifdef NO_PROFILE_COUNTERS
@@ -23863,21 +23873,21 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
if (!flag_plt)
{
if (ASSEMBLER_DIALECT == ASM_INTEL)
- fprintf (file, "1:\tcall\t[QWORD PTR %s@GOTPCREL[rip]]\n",
- mcount_name);
+ fprintf (file, "%s\tcall\t[QWORD PTR %s@GOTPCREL[rip]]\n",
+ label, mcount_name);
else
- fprintf (file, "1:\tcall\t*%s@GOTPCREL(%%rip)\n",
- mcount_name);
+ fprintf (file, "%s\tcall\t*%s@GOTPCREL(%%rip)\n",
+ label, mcount_name);
break;
}
/* fall through */
default:
- x86_print_call_or_nop (file, mcount_name);
+ x86_print_call_or_nop (file, mcount_name, label);
break;
}
}
else
- x86_print_call_or_nop (file, mcount_name);
+ x86_print_call_or_nop (file, mcount_name, label);
}
else if (flag_pic)
{
@@ -23892,11 +23902,13 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
LPREFIX, labelno);
#endif
if (flag_plt)
- x86_print_call_or_nop (file, mcount_name);
+ x86_print_call_or_nop (file, mcount_name, label);
else if (ASSEMBLER_DIALECT == ASM_INTEL)
- fprintf (file, "1:\tcall\t[DWORD PTR %s@GOT[ebx]]\n", mcount_name);
+ fprintf (file, "%s\tcall\t[DWORD PTR %s@GOT[ebx]]\n",
+ label, mcount_name);
else
- fprintf (file, "1:\tcall\t*%s@GOT(%%ebx)\n", mcount_name);
+ fprintf (file, "%s\tcall\t*%s@GOT(%%ebx)\n",
+ label, mcount_name);
}
else
{
@@ -23909,12 +23921,10 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
fprintf (file, "\tmovl\t$%sP%d, %%" PROFILE_COUNT_REGISTER "\n",
LPREFIX, labelno);
#endif
- x86_print_call_or_nop (file, mcount_name);
+ x86_print_call_or_nop (file, mcount_name, label);
}
- if (flag_record_mcount
- || lookup_attribute ("fentry_section",
- DECL_ATTRIBUTES (current_function_decl)))
+ if (fentry_section_p)
{
const char *sname = "__mcount_loc";
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index f7005de..32ef980 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -4573,9 +4573,10 @@
"&& true"
[(set (match_dup 3) (match_dup 2))
(set (match_dup 0)
- (unspec:SI [(match_dup 3) (subreg:SI (match_dup 1) 0)] CRC))]
+ (unspec:SI [(match_dup 3) (match_dup 1)] CRC))]
{
operands[3] = gen_reg_rtx (<MODE>mode);
+ operands[1] = lowpart_subreg (SImode, operands[1], DImode);
})
;; With normal or medium code models, if the only use of a pc-relative
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index cd6d6b9..167e78d 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -10209,17 +10209,33 @@ riscv_fusion_enabled_p(enum riscv_fusion_pairs op)
static bool
riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
{
+ /* If fusion is not enabled, then there's nothing to do. */
+ if (!riscv_macro_fusion_p ())
+ return false;
+
+ /* If PREV is already marked as fused, then we can't fuse CURR with PREV
+ and if we were to fuse them we'd end up with a blob of insns that
+ essentially are an atomic unit which is bad for scheduling. */
+ if (SCHED_GROUP_P (prev))
+ return false;
+
rtx prev_set = single_set (prev);
rtx curr_set = single_set (curr);
/* prev and curr are simple SET insns i.e. no flag setting or branching. */
bool simple_sets_p = prev_set && curr_set && !any_condjump_p (curr);
+ bool sched1 = can_create_pseudo_p ();
- if (!riscv_macro_fusion_p ())
- return false;
+ unsigned int prev_dest_regno = (REG_P (SET_DEST (prev_set))
+ ? REGNO (SET_DEST (prev_set))
+ : FIRST_PSEUDO_REGISTER);
+ unsigned int curr_dest_regno = (REG_P (SET_DEST (curr_set))
+ ? REGNO (SET_DEST (curr_set))
+ : FIRST_PSEUDO_REGISTER);
if (simple_sets_p
&& (riscv_fusion_enabled_p (RISCV_FUSE_ZEXTW)
- || riscv_fusion_enabled_p (RISCV_FUSE_ZEXTWS)))
+ || riscv_fusion_enabled_p (RISCV_FUSE_ZEXTWS))
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (slli) == (set (reg:DI rD)
@@ -10233,19 +10249,23 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& GET_CODE (SET_SRC (curr_set)) == LSHIFTRT
&& REG_P (SET_DEST (prev_set))
&& REG_P (SET_DEST (curr_set))
- && REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO(SET_DEST (curr_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == curr_dest_regno
&& CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
&& CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
&& INTVAL (XEXP (SET_SRC (prev_set), 1)) == 32
- && (( INTVAL (XEXP (SET_SRC (curr_set), 1)) == 32
- && riscv_fusion_enabled_p(RISCV_FUSE_ZEXTW) )
- || ( INTVAL (XEXP (SET_SRC (curr_set), 1)) < 32
- && riscv_fusion_enabled_p(RISCV_FUSE_ZEXTWS))))
- return true;
+ && ((INTVAL (XEXP (SET_SRC (curr_set), 1)) == 32
+ && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTW) )
+ || (INTVAL (XEXP (SET_SRC (curr_set), 1)) < 32
+ && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTWS))))
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_ZEXTWS\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTH))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTH)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (slli) == (set (reg:DI rD)
@@ -10257,16 +10277,20 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& GET_CODE (SET_SRC (curr_set)) == LSHIFTRT
&& REG_P (SET_DEST (prev_set))
&& REG_P (SET_DEST (curr_set))
- && REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO(SET_DEST (curr_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == curr_dest_regno
&& CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
&& CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
&& INTVAL (XEXP (SET_SRC (prev_set), 1)) == 48
&& INTVAL (XEXP (SET_SRC (curr_set), 1)) == 48)
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file,"RISCV_FUSE_ZEXTH\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDINDEXED))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDINDEXED)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (add) == (set (reg:DI rD)
@@ -10275,12 +10299,17 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
(mem:DI (reg:DI rD))) */
if (MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno
&& GET_CODE (SET_SRC (prev_set)) == PLUS
&& REG_P (XEXP (SET_SRC (prev_set), 0))
&& REG_P (XEXP (SET_SRC (prev_set), 1)))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LDINDEXED\n");
+ return true;
+ }
/* We are trying to match the following:
prev (add) == (set (reg:DI rD)
@@ -10290,15 +10319,21 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
|| (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND))
&& MEM_P (XEXP (SET_SRC (curr_set), 0))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == REGNO (SET_DEST (prev_set))
+ && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno
&& GET_CODE (SET_SRC (prev_set)) == PLUS
&& REG_P (XEXP (SET_SRC (prev_set), 0))
&& REG_P (XEXP (SET_SRC (prev_set), 1)))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LDINDEXED\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDPREINCREMENT))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDPREINCREMENT)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (add) == (set (reg:DI rS)
@@ -10307,15 +10342,21 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
(mem:DI (reg:DI rS))) */
if (MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno
&& GET_CODE (SET_SRC (prev_set)) == PLUS
&& REG_P (XEXP (SET_SRC (prev_set), 0))
&& CONST_INT_P (XEXP (SET_SRC (prev_set), 1)))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LDPREINCREMENT\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_ADDI))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_ADDI)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (lui) == (set (reg:DI rD) (const_int UPPER_IMM_20))
@@ -10329,10 +10370,15 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& (GET_CODE (SET_SRC (prev_set)) == HIGH
|| (CONST_INT_P (SET_SRC (prev_set))
&& LUI_OPERAND (INTVAL (SET_SRC (prev_set))))))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_ADDI\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_ADDI))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_ADDI)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (auipc) == (set (reg:DI rD) (unspec:DI [...] UNSPEC_AUIPC))
@@ -10350,38 +10396,64 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
&& SMALL_OPERAND (INTVAL (XEXP (SET_SRC (curr_set), 1))))))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_AUIPC_ADDI\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_LD))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_LD)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (lui) == (set (reg:DI rD) (const_int UPPER_IMM_20))
curr (ld) == (set (reg:DI rD)
(mem:DI (plus:DI (reg:DI rD) (const_int IMM12)))) */
+ /* A LUI_OPERAND accepts (const_int 0), but we won't emit that as LUI. So
+ reject that case explicitly. */
if (CONST_INT_P (SET_SRC (prev_set))
+ && SET_SRC (prev_set) != CONST0_RTX (GET_MODE (SET_DEST (prev_set)))
&& LUI_OPERAND (INTVAL (SET_SRC (prev_set)))
&& MEM_P (SET_SRC (curr_set))
- && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS)
- return true;
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
+ && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS
+ && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno)
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_LD\n");
+ return true;
+ }
if (GET_CODE (SET_SRC (prev_set)) == HIGH
&& MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& GET_CODE (XEXP (SET_SRC (curr_set), 0)) == LO_SUM
- && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)))
- return true;
+ && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno)
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_LD\n");
+ return true;
+ }
if (GET_CODE (SET_SRC (prev_set)) == HIGH
&& (GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
|| GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND)
&& MEM_P (XEXP (SET_SRC (curr_set), 0))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& (GET_CODE (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == LO_SUM
- && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))))
- return true;
+ && (REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))
+ == prev_dest_regno)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_LD\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_LD))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_LD)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (auipc) == (set (reg:DI rD) (unspec:DI [...] UNSPEC_AUIPC))
@@ -10391,8 +10463,13 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
if (GET_CODE (SET_SRC (prev_set)) == UNSPEC
&& XINT (prev_set, 1) == UNSPEC_AUIPC
&& MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS)
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_AUIPC_LD\n");
+ return true;
+ }
}
if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ALIGNED_STD))
@@ -10405,6 +10482,7 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
if (MEM_P (SET_DEST (prev_set))
&& MEM_P (SET_DEST (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
/* We can probably relax this condition. The documentation is a bit
unclear about sub-word cases. So we just model DImode for now. */
&& GET_MODE (SET_DEST (curr_set)) == DImode
@@ -10415,43 +10493,36 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
extract_base_offset_in_addr (SET_DEST (prev_set), &base_prev, &offset_prev);
extract_base_offset_in_addr (SET_DEST (curr_set), &base_curr, &offset_curr);
- /* Fail if we did not find both bases. */
- if (base_prev == NULL_RTX || base_curr == NULL_RTX)
- return false;
-
- /* Fail if either base is not a register. */
- if (!REG_P (base_prev) || !REG_P (base_curr))
- return false;
-
- /* Fail if the bases are not the same register. */
- if (REGNO (base_prev) != REGNO (base_curr))
- return false;
-
- /* Originally the thought was to check MEM_ALIGN, but that was
- reporting incorrect alignments, even for SP/FP accesses, so we
- gave up on that approach. Instead just check for stack/hfp
- which we know are aligned. */
- if (REGNO (base_prev) != STACK_POINTER_REGNUM
- && REGNO (base_prev) != HARD_FRAME_POINTER_REGNUM)
- return false;
-
- /* The two stores must be contained within opposite halves of the
- same 16 byte aligned block of memory. We know that the stack
- pointer and the frame pointer have suitable alignment. So we
- just need to check the offsets of the two stores for suitable
- alignment. */
- /* Get the smaller offset into OFFSET_PREV. */
- if (INTVAL (offset_prev) > INTVAL (offset_curr))
- std::swap (offset_prev, offset_curr);
-
- /* If the smaller offset (OFFSET_PREV) is not 16 byte aligned,
- then fail. */
- if ((INTVAL (offset_prev) % 16) != 0)
- return false;
-
- /* The higher offset must be 8 bytes more than the lower
- offset. */
- return (INTVAL (offset_prev) + 8 == INTVAL (offset_curr));
+ /* Proceed only if we find both bases, both bases are register and
+ bases are the same register. */
+ if (base_prev != NULL_RTX && base_curr != NULL_RTX
+ && REG_P (base_prev) && REG_P (base_curr)
+ && REGNO (base_prev) != REGNO (base_curr)
+ /* The alignment of hte base pointer is more useful than the
+ alignment of the memory reference for determining if we're
+ on opposite sides of a cache line. */
+ && REGNO_POINTER_ALIGN (ORIGINAL_REGNO (base_prev)) >= 128)
+ {
+ /* The two stores must be contained within opposite halves of the
+ same 16 byte aligned block of memory. We know the pointer
+ has suitable alignment, so we just need to check the offsets
+ of the two stores for suitable alignment. */
+
+ /* Get the smaller offset into OFFSET_PREV. */
+ if (INTVAL (offset_prev) > INTVAL (offset_curr))
+ std::swap (offset_prev, offset_curr);
+
+ /* We have a match if the smaller offset (OFFSET_PREV) is 16
+ byte aligned and the higher offset is 8 bytes more than the
+ lower offset. */
+ if ((INTVAL (offset_prev) % 16) == 0
+ && (INTVAL (offset_prev) + 8 == INTVAL (offset_curr)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_ALIGNED_STD\n");
+ return true;
+ }
+ }
}
}
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 3826720..de9c15c 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -18041,9 +18041,34 @@ expand_perm_with_merge (const struct expand_vec_perm_d &d)
static const unsigned char lo_perm_qi_swap[16]
= {17, 1, 19, 3, 21, 5, 23, 7, 25, 9, 27, 11, 29, 13, 31, 15};
+ static const unsigned char hi_perm_qi_di[16]
+ = {0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23};
+ static const unsigned char hi_perm_qi_si[16]
+ = {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23};
+ static const unsigned char hi_perm_qi_hi[16]
+ = {0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23};
+
+ static const unsigned char lo_perm_qi_di[16]
+ = {8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31};
+ static const unsigned char lo_perm_qi_si[16]
+ = {8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31};
+ static const unsigned char lo_perm_qi_hi[16]
+ = {8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31};
+
+ static const unsigned char hi_perm_hi_si[8] = {0, 1, 8, 9, 2, 3, 10, 11};
+ static const unsigned char hi_perm_hi_di[8] = {0, 1, 2, 3, 8, 9, 10, 11};
+
+ static const unsigned char lo_perm_hi_si[8] = {4, 5, 12, 13, 6, 7, 14, 15};
+ static const unsigned char lo_perm_hi_di[8] = {4, 5, 6, 7, 12, 13, 14, 15};
+
+ static const unsigned char hi_perm_si_di[4] = {0, 1, 4, 5};
+
+ static const unsigned char lo_perm_si_di[4] = {2, 3, 6, 7};
+
bool merge_lo_p = false;
bool merge_hi_p = false;
bool swap_operands_p = false;
+ machine_mode mergemode = d.vmode;
if ((d.nelt == 2 && memcmp (d.perm, hi_perm_di, 2) == 0)
|| (d.nelt == 4 && memcmp (d.perm, hi_perm_si, 4) == 0)
@@ -18075,6 +18100,75 @@ expand_perm_with_merge (const struct expand_vec_perm_d &d)
merge_lo_p = true;
swap_operands_p = true;
}
+ else if (d.nelt == 16)
+ {
+ if (memcmp (d.perm, hi_perm_qi_di, 16) == 0)
+ {
+ merge_hi_p = true;
+ mergemode = E_V2DImode;
+ }
+ else if (memcmp (d.perm, hi_perm_qi_si, 16) == 0)
+ {
+ merge_hi_p = true;
+ mergemode = E_V4SImode;
+ }
+ else if (memcmp (d.perm, hi_perm_qi_hi, 16) == 0)
+ {
+ merge_hi_p = true;
+ mergemode = E_V8HImode;
+ }
+ else if (memcmp (d.perm, lo_perm_qi_di, 16) == 0)
+ {
+ merge_lo_p = true;
+ mergemode = E_V2DImode;
+ }
+ else if (memcmp (d.perm, lo_perm_qi_si, 16) == 0)
+ {
+ merge_lo_p = true;
+ mergemode = E_V4SImode;
+ }
+ else if (memcmp (d.perm, lo_perm_qi_hi, 16) == 0)
+ {
+ merge_lo_p = true;
+ mergemode = E_V8HImode;
+ }
+ }
+ else if (d.nelt == 8)
+ {
+ if (memcmp (d.perm, hi_perm_hi_di, 8) == 0)
+ {
+ merge_hi_p = true;
+ mergemode = E_V2DImode;
+ }
+ else if (memcmp (d.perm, hi_perm_hi_si, 8) == 0)
+ {
+ merge_hi_p = true;
+ mergemode = E_V4SImode;
+ }
+ else if (memcmp (d.perm, lo_perm_hi_di, 8) == 0)
+ {
+ merge_lo_p = true;
+ mergemode = E_V2DImode;
+ }
+ else if (memcmp (d.perm, lo_perm_hi_si, 8) == 0)
+ {
+ merge_lo_p = true;
+ mergemode = E_V4SImode;
+ }
+ }
+ else if (d.nelt == 4)
+ {
+ if (memcmp (d.perm, hi_perm_si_di, 4) == 0)
+ {
+ merge_hi_p = true;
+ mergemode = E_V2DImode;
+ }
+ else if (memcmp (d.perm, lo_perm_si_di, 4) == 0)
+ {
+ merge_lo_p = true;
+ mergemode = E_V2DImode;
+ }
+ }
if (!merge_lo_p && !merge_hi_p)
return false;
@@ -18082,7 +18176,7 @@ expand_perm_with_merge (const struct expand_vec_perm_d &d)
if (d.testing_p)
return merge_lo_p || merge_hi_p;
- rtx op0, op1;
+ rtx op0, op1, target = d.target;
if (swap_operands_p)
{
op0 = d.op1;
@@ -18093,9 +18187,77 @@ expand_perm_with_merge (const struct expand_vec_perm_d &d)
op0 = d.op0;
op1 = d.op1;
}
+ if (mergemode != d.vmode)
+ {
+ target = simplify_gen_subreg (mergemode, target, d.vmode, 0);
+ op0 = simplify_gen_subreg (mergemode, op0, d.vmode, 0);
+ op1 = simplify_gen_subreg (mergemode, op1, d.vmode, 0);
+ }
+
+ s390_expand_merge (target, op0, op1, merge_hi_p);
+
+ return true;
+}
+
+/* Try to expand the vector permute operation described by D using the vector
+ pack instruction vpk. Return true if vector pack could be used. */
+static bool
+expand_perm_with_pack (const struct expand_vec_perm_d &d)
+{
+ static const unsigned char qi_hi[16]
+ = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31};
+ static const unsigned char qi_si[16]
+ = {2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31};
+ static const unsigned char qi_di[16]
+ = {4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31};
+
+ static const unsigned char hi_si[8]
+ = {1, 3, 5, 7, 9, 11, 13, 15};
+ static const unsigned char hi_di[8]
+ = {2, 3, 6, 7, 10, 11, 14, 15};
+
+ static const unsigned char si_di[4]
+ = {1, 3, 5, 7};
+
+ machine_mode packmode, resmode;
+ enum insn_code code = CODE_FOR_nothing;
+
+ if (d.nelt == 16 && memcmp (d.perm, qi_hi, 16) == 0)
+ {
+ packmode = E_V8HImode;
+ resmode = E_V16QImode;
+ code = CODE_FOR_vec_pack_trunc_v8hi;
+ }
+ else if ((d.nelt == 16 && memcmp (d.perm, qi_si, 16) == 0)
+ || (d.nelt == 8 && memcmp (d.perm, hi_si, 8) == 0))
+ {
+ packmode = E_V4SImode;
+ resmode = E_V8HImode;
+ code = CODE_FOR_vec_pack_trunc_v4si;
+ }
+ else if ((d.nelt == 16 && memcmp (d.perm, qi_di, 16) == 0)
+ || (d.nelt == 8 && memcmp (d.perm, hi_di, 8) == 0)
+ || (d.nelt == 4 && memcmp (d.perm, si_di, 4) == 0))
+ {
+ packmode = E_V2DImode;
+ resmode = E_V4SImode;
+ code = CODE_FOR_vec_pack_trunc_v2di;
+ }
- s390_expand_merge (d.target, op0, op1, merge_hi_p);
+ if (code == CODE_FOR_nothing)
+ return false;
+ if (d.testing_p)
+ return true;
+ rtx target = simplify_gen_subreg (resmode, d.target, d.vmode, 0);
+ rtx op0 = simplify_gen_subreg (packmode,
+ force_reg (GET_MODE (d.op0), d.op0),
+ d.vmode, 0);
+ rtx op1 = simplify_gen_subreg (packmode,
+ force_reg (GET_MODE (d.op1), d.op1),
+ d.vmode, 0);
+ rtx pat = GEN_FCN (code) (target, op0, op1);
+ emit_insn (pat);
return true;
}
@@ -18322,6 +18484,9 @@ vectorize_vec_perm_const_1 (const struct expand_vec_perm_d &d)
if (expand_perm_with_merge (d))
return true;
+ if (expand_perm_with_pack (d))
+ return true;
+
if (expand_perm_with_vpdi (d))
return true;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ff7582d..b1b173c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+2025-07-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/120716
+ * lambda.cc (finish_lambda_function): Pass cur_stmt_list to
+ prune_lambda_captures.
+
+2025-07-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/120748
+ * lambda.cc (lambda_expr_this_capture): Don't return a FIELD_DECL.
+ * parser.cc (cp_parser_primary_expression): Ignore THIS_FORBIDDEN
+ if cp_unevaluated_operand.
+
+2025-07-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/120940
+ * typeck.cc (cp_build_array_ref): Fix a pasto.
+
+2025-07-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/120684
+ PR c++/118856
+ * constexpr.cc (cxx_eval_constant_expression) [TARGET_EXPR]: Clear
+ the value first if is_complex.
+
2025-07-01 Jakub Jelinek <jakub@redhat.com>
PR c++/120471
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 2a9061a..182cffa 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -823,6 +823,14 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
if (cp_unevaluated_operand)
add_capture_p = false;
+ /* If we captured 'this' but don't have a capture proxy yet, look up the
+ captured 'this' again. */
+ if (this_capture && TREE_CODE (this_capture) == FIELD_DECL)
+ {
+ gcc_assert (!add_capture_p);
+ this_capture = NULL_TREE;
+ }
+
/* Try to default capture 'this' if we can. */
if (!this_capture)
{
@@ -940,6 +948,9 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
result = rvalue (result);
}
+ gcc_checking_assert (!result || result == error_mark_node
+ || TYPE_PTR_P (TREE_TYPE (result)));
+
return result;
}
@@ -1939,7 +1950,7 @@ finish_lambda_function (tree body)
{
finish_function_body (body);
- prune_lambda_captures (body);
+ prune_lambda_captures (cur_stmt_list);
/* Finish the function and generate code for it if necessary. */
tree fn = finish_function (/*inline_p=*/true);
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index b1626ac..617b7cd 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6307,7 +6307,10 @@ cp_parser_primary_expression (cp_parser *parser,
/* Recognize the `this' keyword. */
case RID_THIS:
cp_lexer_consume_token (parser->lexer);
- if (parser->local_variables_forbidden_p & THIS_FORBIDDEN)
+ if ((parser->local_variables_forbidden_p & THIS_FORBIDDEN)
+ /* It's OK to refer to 'this' in an unevaluated operand in a
+ lambda default argument (lambda-targ16.C). */
+ && !cp_unevaluated_operand)
{
error_at (token->location,
"%<this%> may not be used in this context");
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 447fe81..0bf5ae4 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -4004,7 +4004,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
tree op0, op1, op2;
op0 = TREE_OPERAND (array, 0);
op1 = TREE_OPERAND (array, 1);
- op2 = TREE_OPERAND (array, 1);
+ op2 = TREE_OPERAND (array, 2);
if (TREE_SIDE_EFFECTS (idx) || !tree_invariant_p (idx))
{
/* If idx could possibly have some SAVE_EXPRs, turning
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ad11874c..7640e7d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -22466,6 +22466,9 @@ Enable the FlagM2 flag conversion instructions.
Enable the Pointer Authentication Extension.
@item cssc
Enable the Common Short Sequence Compression instructions.
+@item cmpbr
+Enable the shorter compare and branch instructions, @code{cbb}, @code{cbh} and
+@code{cb}.
@item sme
Enable the Scalable Matrix Extension. This is only supported when SVE2 is also
enabled.
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 0ea9c39..d0537d4 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2025-07-03 Andre Vehreschild <vehre@gcc.gnu.org>
+
+ PR fortran/120843
+ * resolve.cc (resolve_operator): Remove conformability check,
+ because it is not in the standard.
+
2025-07-01 Harald Anlauf <anlauf@gmx.de>
* coarray.cc (check_add_new_component): Treat pure and elemental
diff --git a/gcc/match.pd b/gcc/match.pd
index f4416d9..10c2b97 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3500,7 +3500,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
wide_int c2 = wi::to_wide (@2);
wide_int sum = wi::add (c1, c2);
}
- (if (wi::eq_p (sum, wi::max_value (precision, SIGNED)))))))
+ (if (wi::eq_p (sum, wi::max_value (precision, SIGNED))))))
+
+(match (signed_integer_sat_add @0 @1)
+ /* T SUM = (T)((UT)X + (UT)IMM)
+ SAT_S_ADD = (X ^ SUM) < 0 && (X ^ IMM) >= 0 ? (-(T)(X < 0) ^ MAX) : SUM */
+ (cond^ (ge (bit_ior:c (bit_xor:c @0 INTEGER_CST@1)
+ (bit_not (bit_xor:c @0 (nop_convert@2 (plus (nop_convert @0)
+ INTEGER_CST@3)))))
+ integer_zerop)
+ (signed_integer_sat_val @0)
+ @2)
+ (if (wi::eq_p (wi::to_wide (@1), wi::to_wide (@3))))))
/* Saturation sub for signed integer. */
(if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ab15e88..c70aee2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,88 @@
+2025-07-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/120716
+ * g++.dg/cpp0x/lambda/lambda-constexpr3.C: New test.
+ * g++.dg/cpp0x/lambda/lambda-constexpr3a.C: New test.
+
+2025-07-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/120748
+ * g++.dg/cpp2a/lambda-targ16.C: New test.
+ * g++.dg/cpp0x/this1.C: Adjust diagnostics.
+
+2025-07-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/120940
+ * g++.dg/parse/pr120940.C: New test.
+ * g++.dg/warn/Wduplicated-branches9.C: New test.
+
+2025-07-03 Juergen Christ <jchrist@linux.ibm.com>
+
+ * gcc.target/s390/vector/vec-perm-merge-1.c: New test.
+ * gcc.target/s390/vector/vec-perm-pack-1.c: New test.
+
+2025-07-03 Thomas Schwinge <tschwinge@baylibre.com>
+
+ * c-c++-common/gomp/omp_get_num_devices_initial_device.c: Fix.
+ * gfortran.dg/gomp/omp_get_num_devices_initial_device.f90: Likewise.
+
+2025-07-03 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.dg/ipa/pr120295.c (glob): Rename to glob_.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * gcc.target/aarch64/cmpbr.c: Update tests.
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * gcc.target/aarch64/cmpbr.c:
+
+2025-07-03 Karl Meakin <karl.meakin@arm.com>
+
+ * lib/target-supports.exp: Add `cmpbr` to the list of extensions.
+ * gcc.target/aarch64/cmpbr.c: New test.
+
+2025-07-03 Siddhesh Poyarekar <siddhesh@gotplt.org>
+
+ PR tree-optimization/120780
+ * gcc.dg/builtin-dynamic-object-size-pr120780.c: New test case.
+
+2025-07-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/120936
+ * gcc.target/i386/pr120936-1.c: New test
+ * gcc.target/i386/pr120936-2.c: Likewise.
+ * gcc.target/i386/pr120936-3.c: Likewise.
+ * gcc.target/i386/pr120936-4.c: Likewise.
+ * gcc.target/i386/pr120936-5.c: Likewise.
+ * gcc.target/i386/pr120936-6.c: Likewise.
+ * gcc.target/i386/pr120936-7.c: Likewise.
+ * gcc.target/i386/pr120936-8.c: Likewise.
+ * gcc.target/i386/pr120936-9.c: Likewise.
+ * gcc.target/i386/pr120936-10.c: Likewise.
+ * gcc.target/i386/pr120936-11.c: Likewise.
+ * gcc.target/i386/pr120936-12.c: Likewise.
+ * gcc.target/i386/pr93492-3.c: Updated.
+ * gcc.target/i386/pr93492-5.c: Likewise.
+
+2025-07-03 Andre Vehreschild <vehre@gcc.gnu.org>
+
+ PR fortran/120843
+ * gfortran.dg/coarray/coindexed_6.f90: Enhance test to have
+ coarray components covered.
+
+2025-07-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/120908
+ * gcc.target/i386/pr120908.c: New test.
+
+2025-07-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/120684
+ PR c++/118856
+ * g++.dg/cpp23/range-for10.C: New test.
+
2025-07-02 Dimitar Dimitrov <dimitar@dinux.eu>
* gcc.target/riscv/mcpu-xt-c908.c: Disable for E ABI variants.
diff --git a/gcc/testsuite/c-c++-common/gomp/omp_get_num_devices_initial_device.c b/gcc/testsuite/c-c++-common/gomp/omp_get_num_devices_initial_device.c
index 4b17143..6e2c1a8 100644
--- a/gcc/testsuite/c-c++-common/gomp/omp_get_num_devices_initial_device.c
+++ b/gcc/testsuite/c-c++-common/gomp/omp_get_num_devices_initial_device.c
@@ -25,8 +25,8 @@ int f()
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
-/* { dg-final { scan-tree-dump-not "omp_get_num_devices;" "optimized" { target { ! offloading_enabled } } } } */
+/* { dg-final { scan-tree-dump-not "omp_get_num_devices" "optimized" { target { ! offloading_enabled } } } } */
/* { dg-final { scan-tree-dump "return 0;" "optimized" { target { ! offloading_enabled } } } } */
-/* { dg-final { scan-tree-dump-times "omp_get_num_devices;" 1 "optimized" { target offloading_enabled } } } */
+/* { dg-final { scan-tree-dump-times "omp_get_num_devices" 1 "optimized" { target offloading_enabled } } } */
/* { dg-final { scan-tree-dump "_1 = __builtin_omp_get_num_devices \\(\\);\[\\r\\n\]+\[ \]+return _1;" "optimized" { target offloading_enabled } } } */
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3.C
new file mode 100644
index 0000000..6525213
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3.C
@@ -0,0 +1,13 @@
+// PR c++/120716
+// { dg-do compile { target c++11 } }
+
+struct A { int *r; };
+
+void
+foo ()
+{
+ static int i;
+ constexpr A a = { &i };
+ static_assert (a.r == &i, "");
+ [&] { static_assert (a.r != nullptr, ""); } ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3a.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3a.C
new file mode 100644
index 0000000..398e079
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr3a.C
@@ -0,0 +1,12 @@
+// PR c++/120716
+// { dg-do compile { target c++11 } }
+
+struct A { int *const &r; };
+
+void
+foo (int x)
+{
+ constexpr A a = { &x }; // { dg-error "constant" }
+ static_assert (a.r == &x, ""); // { dg-error "non-constant" }
+ [&] { static_assert (a.r != nullptr, ""); } (); // { dg-error "non-constant" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/this1.C b/gcc/testsuite/g++.dg/cpp0x/this1.C
index 486e045..e70cd1a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/this1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/this1.C
@@ -8,10 +8,10 @@ struct S1 {
void m3 () noexcept(noexcept(this->a)) { }
void m4 () noexcept(noexcept(this)) { }
- static auto m5 () -> decltype(this->a) { return 0; } // { dg-error ".this. may not be used in this context" }
- static auto m6 () -> decltype(this) { return 0; } // { dg-error ".this. may not be used in this context" }
- static void m7 () noexcept(noexcept(this->a)) { } // { dg-error ".this. may not be used in this context" }
- static void m8 () noexcept(noexcept(this)) { } // { dg-error ".this. may not be used in this context" }
+ static auto m5 () -> decltype(this->a) { return 0; } // { dg-error ".this." }
+ static auto m6 () -> decltype(this) { return 0; } // { dg-error ".this." }
+ static void m7 () noexcept(noexcept(this->a)) { } // { dg-error ".this." }
+ static void m8 () noexcept(noexcept(this)) { } // { dg-error ".this." }
};
template <typename T>
@@ -41,6 +41,6 @@ test ()
}
struct S5 {
- friend auto bar() -> decltype(this); // { dg-error ".this. may not be used in this context" }
+ friend auto bar() -> decltype(this); // { dg-error ".this." }
auto bar2() -> decltype(this);
};
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ16.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ16.C
new file mode 100644
index 0000000..11f2337
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ16.C
@@ -0,0 +1,29 @@
+// PR c++/120748
+// From Clang cxx20-lambda-decltype-this.cpp.
+// { dg-do compile { target c++20 } }
+
+namespace PR45881 {
+struct A {
+ void f();
+};
+int id(A*);
+void A::f() {
+ auto z = [*this](auto z2, decltype(z2(this)) z3){};
+ z(id,3);
+}
+
+struct B {
+ void f();
+};
+void B::f() {
+ auto z = []<typename TT, typename TTT=decltype(TT()(this))>(){return 0;};
+ z.template operator()<int(*)(B*)>();
+}
+struct C {
+ void f();
+};
+void C::f() {
+ auto z = []<typename TT, decltype(TT()(this)) n>(){return 0;};
+ z.template operator()<int(*)(C*), 8>();
+}
+} // namespace PR45881
diff --git a/gcc/testsuite/g++.dg/parse/pr120940.C b/gcc/testsuite/g++.dg/parse/pr120940.C
new file mode 100644
index 0000000..5da36b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr120940.C
@@ -0,0 +1,18 @@
+// PR c++/120940
+// { dg-do run }
+
+int a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+int b[8] = { 9, 10, 11, 12, 13, 14, 15, 16 };
+
+__attribute__((noipa)) int
+foo (int x, int y)
+{
+ return (x ? a : b)[y];
+}
+
+int
+main ()
+{
+ if (foo (1, 4) != 5 || foo (0, 6) != 15)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wduplicated-branches9.C b/gcc/testsuite/g++.dg/warn/Wduplicated-branches9.C
new file mode 100644
index 0000000..f9fafcd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wduplicated-branches9.C
@@ -0,0 +1,11 @@
+// PR c++/120940
+// { dg-do compile }
+// { dg-options "-Wduplicated-branches" }
+
+static char a[16][8], b[16][8];
+
+char *
+foo (int x, int y)
+{
+ return (x ? a : b)[y];
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr120807.c b/gcc/testsuite/gcc.c-torture/compile/pr120807.c
new file mode 100644
index 0000000..9b37e60
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr120807.c
@@ -0,0 +1,20 @@
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef struct
+{
+ uint32_t dword[2];
+ uint8_t byte[8];
+} reg64_t;
+reg64_t TestF20F_opgd, TestF20F_oped;
+
+void
+TestF20F ()
+{
+ TestF20F_opgd.dword[0] ^= TestF20F_oped.byte[0];
+ for (int i = 0; i < 8; i++)
+ if (TestF20F_opgd.dword[0] & 1)
+ TestF20F_opgd.dword[0] = TestF20F_opgd.dword[0] >> 1 ^ (uint32_t)2197175160UL;
+ else
+ TestF20F_opgd.dword[0] = TestF20F_opgd.dword[0] >> 1;
+}
diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c
new file mode 100644
index 0000000..0d6593e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c
@@ -0,0 +1,233 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "builtin-object-size-common.h"
+typedef __SIZE_TYPE__ size_t;
+#define NUM_MCAST_RATE 6
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+struct inner
+{
+ int dummy[4];
+};
+
+struct container
+{
+ int mcast_rate[NUM_MCAST_RATE];
+ struct inner mesh;
+};
+
+static void
+test1_child (struct inner *ifmsh, size_t expected)
+{
+ struct container *sdata =
+ (struct container *) ((void *) ifmsh
+ - __builtin_offsetof (struct container, mesh));
+
+ if (__builtin_dynamic_object_size (sdata->mcast_rate, 1)
+ != sizeof (sdata->mcast_rate))
+ FAIL ();
+
+ if (__builtin_dynamic_object_size (&sdata->mesh, 1) != expected)
+ FAIL ();
+}
+
+void
+__attribute__((noinline))
+test1 (size_t sz)
+{
+ struct container *sdata = __builtin_malloc (sz);
+ struct inner *ifmsh = &sdata->mesh;
+
+ test1_child (ifmsh,
+ (sz > sizeof (sdata->mcast_rate)
+ ? sz - sizeof (sdata->mcast_rate) : 0));
+
+ __builtin_free (sdata);
+}
+
+struct container2
+{
+ int mcast_rate[NUM_MCAST_RATE];
+ union
+ {
+ int dummy;
+ double dbl;
+ struct inner mesh;
+ } u;
+};
+
+static void
+test2_child (struct inner *ifmsh, size_t sz)
+{
+ struct container2 *sdata =
+ (struct container2 *) ((void *) ifmsh
+ - __builtin_offsetof (struct container2, u.mesh));
+
+ if (__builtin_dynamic_object_size (sdata->mcast_rate, 1)
+ != sizeof (sdata->mcast_rate))
+ FAIL ();
+
+ size_t diff = sizeof (*sdata) - sz;
+ size_t expected = MIN(sizeof (double), MAX (sizeof (sdata->u), diff) - diff);
+
+ if (__builtin_dynamic_object_size (&sdata->u.dbl, 1) != expected)
+ FAIL ();
+
+ expected = MAX (sizeof (sdata->u.mesh), diff) - diff;
+ if (__builtin_dynamic_object_size (&sdata->u.mesh, 1) != expected)
+ FAIL ();
+}
+
+void
+__attribute__((noinline))
+test2 (size_t sz)
+{
+ struct container2 *sdata = __builtin_malloc (sz);
+ struct inner *ifmsh = &sdata->u.mesh;
+
+ test2_child (ifmsh, sz);;
+
+ __builtin_free (sdata);
+}
+
+struct container3
+{
+ int mcast_rate[NUM_MCAST_RATE];
+ char mesh[8];
+};
+
+static void
+test3_child (char ifmsh[], size_t expected)
+{
+ struct container3 *sdata =
+ (struct container3 *) ((void *) ifmsh
+ - __builtin_offsetof (struct container3, mesh));
+
+ if (__builtin_dynamic_object_size (sdata->mcast_rate, 1)
+ != sizeof (sdata->mcast_rate))
+ FAIL ();
+
+ if (__builtin_dynamic_object_size (sdata->mesh, 1) != expected)
+ FAIL ();
+}
+
+void
+__attribute__((noinline))
+test3 (size_t sz)
+{
+ struct container3 *sdata = __builtin_malloc (sz);
+ char *ifmsh = sdata->mesh;
+ size_t diff = sizeof (*sdata) - sz;
+
+ test3_child (ifmsh, MAX(sizeof (sdata->mesh), diff) - diff);
+
+ __builtin_free (sdata);
+}
+
+
+struct container4
+{
+ int mcast_rate[NUM_MCAST_RATE];
+ struct
+ {
+ int dummy;
+ struct inner mesh;
+ } s;
+};
+
+static void
+test4_child (struct inner *ifmsh, size_t expected)
+{
+ struct container4 *sdata =
+ (struct container4 *) ((void *) ifmsh
+ - __builtin_offsetof (struct container4, s.mesh));
+
+
+ if (__builtin_dynamic_object_size (sdata->mcast_rate, 1)
+ != sizeof (sdata->mcast_rate))
+ FAIL ();
+
+ if (__builtin_dynamic_object_size (&sdata->s.mesh, 1) != expected)
+ FAIL ();
+}
+
+void
+__attribute__((noinline))
+test4 (size_t sz)
+{
+ struct container4 *sdata = __builtin_malloc (sz);
+ struct inner *ifmsh = &sdata->s.mesh;
+ size_t diff = sizeof (*sdata) - sz;
+
+ test4_child (ifmsh, MAX(sizeof (sdata->s.mesh), diff) - diff);
+
+ __builtin_free (sdata);
+}
+
+struct container5
+{
+ int mcast_rate[NUM_MCAST_RATE];
+ struct
+ {
+ int dummy;
+ struct inner *mesh;
+ } s;
+};
+
+static void
+test5_child (struct inner **ifmsh, size_t expected)
+{
+ struct container5 *sdata =
+ (struct container5 *) ((void *) ifmsh
+ - __builtin_offsetof (struct container5, s.mesh));
+
+
+ if (__builtin_dynamic_object_size (sdata->mcast_rate, 1)
+ != sizeof (sdata->mcast_rate))
+ FAIL ();
+
+ if (__builtin_dynamic_object_size (&sdata->s.mesh, 1) != expected)
+ FAIL ();
+}
+
+void
+__attribute__((noinline))
+test5 (size_t sz)
+{
+ struct container5 *sdata = __builtin_malloc (sz);
+ struct inner **ifmsh = &sdata->s.mesh;
+ size_t diff = sizeof (*sdata) - sz;
+
+ test5_child (ifmsh, MAX(sizeof (sdata->s.mesh), diff) - diff);
+
+ __builtin_free (sdata);
+}
+
+int
+main (size_t sz)
+{
+ test1 (sizeof (struct container));
+ test1 (sizeof (struct container) - sizeof (int));
+ test1 (sizeof (int) * NUM_MCAST_RATE - 1);
+
+ test2 (sizeof (struct container2));
+ test2 (sizeof (struct container2) - sizeof (int));
+ test2 (sizeof (int) * NUM_MCAST_RATE - 1);
+
+ test3 (sizeof (struct container3));
+ test3 (sizeof (struct container3) - sizeof (int));
+ test3 (sizeof (int) * NUM_MCAST_RATE - 1);
+
+ test4 (sizeof (struct container4));
+ test4 (sizeof (struct container4) - sizeof (int));
+ test4 (sizeof (int) * NUM_MCAST_RATE - 1);
+
+ test5 (sizeof (struct container5));
+ test5 (sizeof (struct container5) - sizeof (int));
+ test5 (sizeof (int) * NUM_MCAST_RATE - 1);
+
+ DONE ();
+}
diff --git a/gcc/testsuite/gcc.dg/ipa/pr120295.c b/gcc/testsuite/gcc.dg/ipa/pr120295.c
index 2033ee9..4d5a266 100644
--- a/gcc/testsuite/gcc.dg/ipa/pr120295.c
+++ b/gcc/testsuite/gcc.dg/ipa/pr120295.c
@@ -9,10 +9,10 @@ char c, k, g, e;
short d[2] = {0};
int *i = &j;
-volatile int glob;
+volatile int glob_;
void __attribute__((noipa)) sth (const char *, int a)
{
- glob = a;
+ glob_ = a;
return;
}
diff --git a/gcc/testsuite/gcc.dg/ubsan/pr120837.c b/gcc/testsuite/gcc.dg/ubsan/pr120837.c
new file mode 100644
index 0000000..97c85c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/pr120837.c
@@ -0,0 +1,32 @@
+/* PR c/120837 */
+/* { dg-do run } */
+/* { dg-options "-O1 -fsanitize=undefined -fno-sanitize-recover=undefined" } */
+
+[[gnu::noipa]] void
+bar (void **x, void **y)
+{
+ x[0] = 0;
+ x[1] = 0;
+ x[2] = 0;
+ y[0] = 0;
+ y[1] = 0;
+ y[2] = 0;
+ y[3] = 0;
+ y[4] = 0;
+}
+
+[[gnu::noipa]] void *
+foo (int x, int y)
+{
+ void *a[3];
+ void *b[5];
+ bar (a, b);
+ return (x > y ? b : a)[y - 1];
+}
+
+int
+main ()
+{
+ if (foo (2, 1) != 0)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/cmpbr.c b/gcc/testsuite/gcc.target/aarch64/cmpbr.c
new file mode 100644
index 0000000..a86af9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cmpbr.c
@@ -0,0 +1,1824 @@
+// Test that the instructions added by FEAT_CMPBR are emitted
+// { dg-do compile }
+// { dg-do-if assemble { target aarch64_asm_cmpbr_ok } }
+// { dg-options "-march=armv9.5-a+cmpbr -O2" }
+// { dg-final { check-function-bodies "**" "*/" "" { target *-*-* } {\.L[0-9]+} } }
+
+#include <stdint.h>
+
+typedef uint8_t u8;
+typedef int8_t i8;
+
+typedef uint16_t u16;
+typedef int16_t i16;
+
+typedef uint32_t u32;
+typedef int32_t i32;
+
+typedef uint64_t u64;
+typedef int64_t i64;
+
+int taken();
+int not_taken();
+
+#define COMPARE(ty, name, op, rhs) \
+ int ty##_x0_##name##_##rhs(ty x0, ty x1) { \
+ return __builtin_expect(x0 op rhs, 0) ? taken() : not_taken(); \
+ }
+
+#define COMPARE_ALL(unsigned_ty, signed_ty, rhs) \
+ COMPARE(unsigned_ty, eq, ==, rhs); \
+ COMPARE(unsigned_ty, ne, !=, rhs); \
+ \
+ COMPARE(unsigned_ty, ult, <, rhs); \
+ COMPARE(unsigned_ty, ule, <=, rhs); \
+ COMPARE(unsigned_ty, ugt, >, rhs); \
+ COMPARE(unsigned_ty, uge, >=, rhs); \
+ \
+ COMPARE(signed_ty, slt, <, rhs); \
+ COMPARE(signed_ty, sle, <=, rhs); \
+ COMPARE(signed_ty, sgt, >, rhs); \
+ COMPARE(signed_ty, sge, >=, rhs);
+
+// ==== CBB<cc> (register) ====
+COMPARE_ALL(u8, i8, x1);
+
+// ==== CBH<cc> (register) ====
+COMPARE_ALL(u16, i16, x1);
+
+// ==== CB<cc> (register) ====
+COMPARE_ALL(u32, i32, x1);
+COMPARE_ALL(u64, i64, x1);
+
+// ==== CB<cc> (immediate) ====
+COMPARE_ALL(u32, i32, 42);
+COMPARE_ALL(u64, i64, 42);
+
+// ==== Special cases ====
+// Comparisons against the immediate 0 can be done for all types,
+// because we can use the wzr/xzr register as one of the operands.
+// However, we should prefer to use CBZ/CBNZ or TBZ/TBNZ when possible,
+// because they have larger range.
+COMPARE_ALL(u8, i8, 0);
+COMPARE_ALL(u16, i16, 0);
+COMPARE_ALL(u32, i32, 0);
+COMPARE_ALL(u64, i64, 0);
+
+// CBB and CBH cannot have immediate operands.
+// Instead we have to do a MOV+CB.
+COMPARE_ALL(u8, i8, 42);
+COMPARE_ALL(u16, i16, 42);
+
+// 64 is out of the range for immediate operands (0 to 63).
+// * For 8/16-bit types, use a MOV+CB as above.
+// * For 32/64-bit types, use a CMP+B<cc> instead,
+// because B<cc> has a longer range than CB<cc>.
+COMPARE_ALL(u8, i8, 64);
+COMPARE_ALL(u16, i16, 64);
+COMPARE_ALL(u32, i32, 64);
+COMPARE_ALL(u64, i64, 64);
+
+// 4098 is out of the range for CMP (0 to 4095, optionally shifted by left by 12
+// bits), but it can be materialized in a single MOV.
+COMPARE_ALL(u16, i16, 4098);
+COMPARE_ALL(u32, i32, 4098);
+COMPARE_ALL(u64, i64, 4098);
+
+// If the branch destination is out of range (1KiB), we have to generate an
+// extra B instruction (which can handle larger displacements) and branch around
+// it
+
+// clang-format off
+#define STORE_1() z = 0;
+#define STORE_2() STORE_1() STORE_1()
+#define STORE_4() STORE_2() STORE_2()
+#define STORE_8() STORE_4() STORE_4()
+#define STORE_16() STORE_8() STORE_8()
+#define STORE_32() STORE_16() STORE_16()
+#define STORE_64() STORE_32() STORE_32()
+#define STORE_128() STORE_64() STORE_64()
+#define STORE_256() STORE_128() STORE_128()
+// clang-format on
+
+#define FAR_BRANCH(ty, rhs) \
+ int far_branch_##ty##_x0_eq_##rhs(ty x0, ty x1) { \
+ volatile int z = 0; \
+ if (__builtin_expect(x0 == rhs, 1)) { \
+ STORE_256(); \
+ } \
+ return taken(); \
+ }
+
+FAR_BRANCH(u8, x1);
+FAR_BRANCH(u16, x1);
+FAR_BRANCH(u32, x1);
+FAR_BRANCH(u64, x1);
+
+FAR_BRANCH(u8, 42);
+FAR_BRANCH(u16, 42);
+FAR_BRANCH(u32, 42);
+FAR_BRANCH(u64, 42);
+
+/*
+** u8_x0_eq_x1:
+** cbbeq w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_ne_x1:
+** cbbne w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_ult_x1:
+** cbbhi w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_ule_x1:
+** cbbhs w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_ugt_x1:
+** cbblo w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_uge_x1:
+** cbbls w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i8_x0_slt_x1:
+** cbbgt w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i8_x0_sle_x1:
+** cbbge w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i8_x0_sgt_x1:
+** cbblt w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i8_x0_sge_x1:
+** cbble w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_eq_x1:
+** cbheq w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_ne_x1:
+** cbhne w0|w1, w1|w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_ult_x1:
+** cbhhi w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_ule_x1:
+** cbhhs w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_ugt_x1:
+** cbhlo w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_uge_x1:
+** cbhls w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i16_x0_slt_x1:
+** cbhgt w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i16_x0_sle_x1:
+** cbhge w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i16_x0_sgt_x1:
+** cbhlt w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i16_x0_sge_x1:
+** cbhle w1, w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_eq_x1:
+** cbeq w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ne_x1:
+** cbne w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ult_x1:
+** cblo w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ule_x1:
+** cbls w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ugt_x1:
+** cbhi w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_uge_x1:
+** cbhs w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_slt_x1:
+** cblt w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sle_x1:
+** cble w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sgt_x1:
+** cbgt w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sge_x1:
+** cbge w0, w1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_eq_x1:
+** cbeq x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ne_x1:
+** cbne x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ult_x1:
+** cblo x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ule_x1:
+** cbls x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ugt_x1:
+** cbhi x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_uge_x1:
+** cbhs x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_slt_x1:
+** cblt x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sle_x1:
+** cble x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sgt_x1:
+** cbgt x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sge_x1:
+** cbge x0, x1, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_eq_42:
+** cbeq w0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ne_42:
+** cbne w0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ult_42:
+** cbls w0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ule_42:
+** cbls w0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ugt_42:
+** cbhi w0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_uge_42:
+** cbhi w0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_slt_42:
+** cble w0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sle_42:
+** cble w0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sgt_42:
+** cbgt w0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sge_42:
+** cbgt w0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_eq_42:
+** cbeq x0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ne_42:
+** cbne x0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ult_42:
+** cbls x0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ule_42:
+** cbls x0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ugt_42:
+** cbhi x0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_uge_42:
+** cbhi x0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_slt_42:
+** cble x0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sle_42:
+** cble x0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sgt_42:
+** cbgt x0, 42, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sge_42:
+** cbgt x0, 41, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_eq_0:
+** cbbeq w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_ne_0:
+** cbbne w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_ult_0:
+** b not_taken
+*/
+
+/*
+** u8_x0_ule_0:
+** cbbeq w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_ugt_0:
+** cbbne w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_uge_0:
+** b taken
+*/
+
+/*
+** i8_x0_slt_0:
+** tbnz w0, #7, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i8_x0_sle_0:
+** cbble w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i8_x0_sgt_0:
+** cbbgt w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i8_x0_sge_0:
+** tbz w0, #7, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_eq_0:
+** cbheq w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_ne_0:
+** cbhne w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_ult_0:
+** b not_taken
+*/
+
+/*
+** u16_x0_ule_0:
+** cbheq w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_ugt_0:
+** cbhne w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_uge_0:
+** b taken
+*/
+
+/*
+** i16_x0_slt_0:
+** tbnz w0, #15, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i16_x0_sle_0:
+** cbhle w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i16_x0_sgt_0:
+** cbhgt w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i16_x0_sge_0:
+** tbz w0, #15, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_eq_0:
+** cbz w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ne_0:
+** cbnz w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ult_0:
+** b not_taken
+*/
+
+/*
+** u32_x0_ule_0:
+** cbz w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ugt_0:
+** cbnz w0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_uge_0:
+** b taken
+*/
+
+/*
+** i32_x0_slt_0:
+** tbnz w0, #31, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sle_0:
+** cble w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sgt_0:
+** cbgt w0, wzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sge_0:
+** tbz w0, #31, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_eq_0:
+** cbz x0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ne_0:
+** cbnz x0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ult_0:
+** b not_taken
+*/
+
+/*
+** u64_x0_ule_0:
+** cbz x0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ugt_0:
+** cbnz x0, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_uge_0:
+** b taken
+*/
+
+/*
+** i64_x0_slt_0:
+** tbnz x0, #63, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sle_0:
+** cble x0, xzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sgt_0:
+** cbgt x0, xzr, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sge_0:
+** tbz x0, #63, .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u8_x0_eq_42:
+** mov w([0-9]+), 42
+** cbbeq w0, w\1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ne_42:
+** mov (w[0-9]+), 42
+** cbbne w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ult_42:
+** mov (w[0-9]+), 41
+** cbbls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ule_42:
+** mov (w[0-9]+), 42
+** cbbls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ugt_42:
+** mov (w[0-9]+), 42
+** cbbhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_uge_42:
+** mov (w[0-9]+), 41
+** cbbhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_slt_42:
+** mov (w[0-9]+), 41
+** cbble w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_sle_42:
+** mov (w[0-9]+), 42
+** cbble w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_sgt_42:
+** mov (w[0-9]+), 42
+** cbbgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_sge_42:
+** mov (w[0-9]+), 41
+** cbbgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_eq_42:
+** mov w([0-9]+), 42
+** cbheq w0, w\1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ne_42:
+** mov (w[0-9]+), 42
+** cbhne w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ult_42:
+** mov (w[0-9]+), 41
+** cbhls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ule_42:
+** mov (w[0-9]+), 42
+** cbhls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ugt_42:
+** mov (w[0-9]+), 42
+** cbhhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_uge_42:
+** mov (w[0-9]+), 41
+** cbhhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_slt_42:
+** mov (w[0-9]+), 41
+** cbhle w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sle_42:
+** mov (w[0-9]+), 42
+** cbhle w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sgt_42:
+** mov (w[0-9]+), 42
+** cbhgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sge_42:
+** mov (w[0-9]+), 41
+** cbhgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_eq_64:
+** mov w([0-9]+), 64
+** cbbeq w0, w\1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ne_64:
+** mov (w[0-9]+), 64
+** cbbne w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ult_64:
+** mov (w[0-9]+), 63
+** cbbls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ule_64:
+** mov (w[0-9]+), 64
+** cbbls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_ugt_64:
+** mov (w[0-9]+), 64
+** cbbhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u8_x0_uge_64:
+** mov (w[0-9]+), 63
+** cbbhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_slt_64:
+** mov (w[0-9]+), 63
+** cbble w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_sle_64:
+** mov (w[0-9]+), 64
+** cbble w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_sgt_64:
+** mov (w[0-9]+), 64
+** cbbgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i8_x0_sge_64:
+** mov (w[0-9]+), 63
+** cbbgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_eq_64:
+** mov w([0-9]+), 64
+** cbheq w0, w\1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ne_64:
+** mov (w[0-9]+), 64
+** cbhne w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ult_64:
+** mov (w[0-9]+), 63
+** cbhls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ule_64:
+** mov (w[0-9]+), 64
+** cbhls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ugt_64:
+** mov (w[0-9]+), 64
+** cbhhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_uge_64:
+** mov (w[0-9]+), 63
+** cbhhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_slt_64:
+** mov (w[0-9]+), 63
+** cbhle w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sle_64:
+** mov (w[0-9]+), 64
+** cbhle w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sgt_64:
+** mov (w[0-9]+), 64
+** cbhgt w0, w1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sge_64:
+** mov (w[0-9]+), 63
+** cbhgt w0, w1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u32_x0_eq_64:
+** cmp w0, 64
+** beq .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ne_64:
+** cmp w0, 64
+** bne .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ult_64:
+** cbhi w0, 63, .L([0-9]+)
+** b taken
+** .L\1:
+** b not_taken
+*/
+
+/*
+** u32_x0_ule_64:
+** cmp w0, 64
+** bls .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_ugt_64:
+** cmp w0, 64
+** bhi .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u32_x0_uge_64:
+** cmp w0, 63
+** bhi .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_slt_64:
+** cbgt w0, 63, .L([0-9]+)
+** b taken
+** .L\1:
+** b not_taken
+*/
+
+/*
+** i32_x0_sle_64:
+** cmp w0, 64
+** ble .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sgt_64:
+** cmp w0, 64
+** bgt .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i32_x0_sge_64:
+** cmp w0, 63
+** bgt .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_eq_64:
+** cmp x0, 64
+** beq .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ne_64:
+** cmp x0, 64
+** bne .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ult_64:
+** cbhi x0, 63, .L([0-9]+)
+** b taken
+** .L\1:
+** b not_taken
+*/
+
+/*
+** u64_x0_ule_64:
+** cmp x0, 64
+** bls .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_ugt_64:
+** cmp x0, 64
+** bhi .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u64_x0_uge_64:
+** cmp x0, 63
+** bhi .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_slt_64:
+** cbgt x0, 63, .L([0-9]+)
+** b taken
+** .L\1:
+** b not_taken
+*/
+
+/*
+** i64_x0_sle_64:
+** cmp x0, 64
+** ble .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sgt_64:
+** cmp x0, 64
+** bgt .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** i64_x0_sge_64:
+** cmp x0, 63
+** bgt .L([0-9]+)
+** b not_taken
+** .L\1:
+** b taken
+*/
+
+/*
+** u16_x0_eq_4098:
+** mov w([0-9]+), 4098
+** cbheq w0, w\1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ne_4098:
+** mov (w[0-9]+), 4098
+** cbhne w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ult_4098:
+** mov (w[0-9]+), 4097
+** cbhls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ule_4098:
+** mov (w[0-9]+), 4098
+** cbhls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_ugt_4098:
+** mov (w[0-9]+), 4098
+** cbhhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u16_x0_uge_4098:
+** mov (w[0-9]+), 4097
+** cbhhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_slt_4098:
+** mov (w[0-9]+), 4097
+** cbhle w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sle_4098:
+** mov (w[0-9]+), 4098
+** cbhle w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sgt_4098:
+** mov (w[0-9]+), 4098
+** cbhgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i16_x0_sge_4098:
+** mov (w[0-9]+), 4097
+** cbhgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u32_x0_eq_4098:
+** mov w([0-9]+), 4098
+** cbeq w0, w\1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u32_x0_ne_4098:
+** mov (w[0-9]+), 4098
+** cbne w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u32_x0_ult_4098:
+** mov (w[0-9]+), 4097
+** cbls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u32_x0_ule_4098:
+** mov (w[0-9]+), 4098
+** cbls w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u32_x0_ugt_4098:
+** mov (w[0-9]+), 4098
+** cbhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u32_x0_uge_4098:
+** mov (w[0-9]+), 4097
+** cbhi w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i32_x0_slt_4098:
+** mov (w[0-9]+), 4097
+** cble w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i32_x0_sle_4098:
+** mov (w[0-9]+), 4098
+** cble w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i32_x0_sgt_4098:
+** mov (w[0-9]+), 4098
+** cbgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i32_x0_sge_4098:
+** mov (w[0-9]+), 4097
+** cbgt w0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u64_x0_eq_4098:
+** mov x([0-9]+), 4098
+** cbeq x0, x\1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u64_x0_ne_4098:
+** mov (x[0-9]+), 4098
+** cbne x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u64_x0_ult_4098:
+** mov (x[0-9]+), 4097
+** cbls x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u64_x0_ule_4098:
+** mov (x[0-9]+), 4098
+** cbls x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u64_x0_ugt_4098:
+** mov (x[0-9]+), 4098
+** cbhi x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** u64_x0_uge_4098:
+** mov (x[0-9]+), 4097
+** cbhi x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i64_x0_slt_4098:
+** mov (x[0-9]+), 4097
+** cble x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i64_x0_sle_4098:
+** mov (x[0-9]+), 4098
+** cble x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i64_x0_sgt_4098:
+** mov (x[0-9]+), 4098
+** cbgt x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** i64_x0_sge_4098:
+** mov (x[0-9]+), 4097
+** cbgt x0, \1, .L([0-9]+)
+** b not_taken
+** .L\2:
+** b taken
+*/
+
+/*
+** far_branch_u8_x0_eq_x1:
+** sub sp, sp, #16
+** str wzr, \[sp, 12\]
+** cbbeq w0|w1, w1|w0, .L([0-9]+)
+** b .L([0-9]+)
+** .L\1:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\2:
+** add sp, sp, 16
+** b taken
+*/
+
+/*
+** far_branch_u16_x0_eq_x1:
+** sub sp, sp, #16
+** str wzr, \[sp, 12\]
+** cbheq w0|w1, w1|w0, .L([0-9]+)
+** b .L([0-9]+)
+** .L\1:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\2:
+** add sp, sp, 16
+** b taken
+*/
+
+/*
+** far_branch_u32_x0_eq_x1:
+** sub sp, sp, #16
+** str wzr, \[sp, 12\]
+** cbeq w0, w1, .L([0-9]+)
+** b .L([0-9]+)
+** .L\1:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\2:
+** add sp, sp, 16
+** b taken
+*/
+
+/*
+** far_branch_u64_x0_eq_x1:
+** sub sp, sp, #16
+** str wzr, \[sp, 12\]
+** cbeq x0, x1, .L([0-9]+)
+** b .L([0-9]+)
+** .L\1:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\2:
+** add sp, sp, 16
+** b taken
+*/
+
+/*
+** far_branch_u8_x0_eq_42:
+** sub sp, sp, #16
+** mov w([0-9]+), 42
+** str wzr, \[sp, 12\]
+** cbbeq w0, w\1, .L([0-9]+)
+** b .L([0-9]+)
+** .L\2:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\3:
+** add sp, sp, 16
+** b taken
+*/
+
+/*
+** far_branch_u16_x0_eq_42:
+** sub sp, sp, #16
+** mov w([0-9]+), 42
+** str wzr, \[sp, 12\]
+** cbheq w0, w\1, .L([0-9]+)
+** b .L([0-9]+)
+** .L\2:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\3:
+** add sp, sp, 16
+** b taken
+*/
+
+/*
+** far_branch_u32_x0_eq_42:
+** sub sp, sp, #16
+** str wzr, \[sp, 12\]
+** cbeq w0, 42, .L([0-9]+)
+** b .L([0-9]+)
+** .L\1:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\2:
+** add sp, sp, 16
+** b taken
+*/
+
+/*
+** far_branch_u64_x0_eq_42:
+** sub sp, sp, #16
+** str wzr, \[sp, 12\]
+** cbeq x0, 42, .L([0-9]+)
+** b .L([0-9]+)
+** .L\1:
+** str wzr, \[sp, 12\]
+** ...
+** str wzr, \[sp, 12\]
+** .L\2:
+** add sp, sp, 16
+** b taken
+*/
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-1.c b/gcc/testsuite/gcc.target/i386/pr120936-1.c
new file mode 100644
index 0000000..a20680d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -pg -mno-fentry -fno-pic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+** call mcount
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-10.c b/gcc/testsuite/gcc.target/i386/pr120936-10.c
new file mode 100644
index 0000000..ab95b08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-10.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { fpic && lp64 } } } */
+/* { dg-options "-O2 -mcmodel=large -pg -mno-fentry -fpic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^(1|\t?\.)} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+**1: movabsq \$_GLOBAL_OFFSET_TABLE_-1b, %r11
+** leaq 1b\(%rip\), %r10
+** addq %r11, %r10
+** movabsq \$mcount@PLTOFF, %r11
+** addq %r11, %r10
+** call \*%r10
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-11.c b/gcc/testsuite/gcc.target/i386/pr120936-11.c
new file mode 100644
index 0000000..3e39dfe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-11.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { fpic && lp64 } } } */
+/* { dg-options "-O2 -mrecord-mcount -mcmodel=large -pg -mno-fentry -fno-pic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^(1|\t?\.)} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+**1: movabsq \$mcount, %r10
+** call \*%r10
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-12.c b/gcc/testsuite/gcc.target/i386/pr120936-12.c
new file mode 100644
index 0000000..b5a2aac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-12.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { fpic && lp64 } } } */
+/* { dg-options "-O2 -mcmodel=large -mrecord-mcount -pg -mno-fentry -fpic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^(1|\t?\.)} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+**1: movabsq \$_GLOBAL_OFFSET_TABLE_-1b, %r11
+** leaq 1b\(%rip\), %r10
+** addq %r11, %r10
+** movabsq \$mcount@PLTOFF, %r11
+** addq %r11, %r10
+** call \*%r10
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-2.c b/gcc/testsuite/gcc.target/i386/pr120936-2.c
new file mode 100644
index 0000000..0835658
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -pg -mno-fentry -fpic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+** call mcount@PLT
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-3.c b/gcc/testsuite/gcc.target/i386/pr120936-3.c
new file mode 100644
index 0000000..dc0a8f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -mnop-mcount -pg -mno-fentry -fno-pic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+** .byte 0x0f, 0x1f, 0x44, 0x00, 0x00
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-4.c b/gcc/testsuite/gcc.target/i386/pr120936-4.c
new file mode 100644
index 0000000..2420f0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -pg -mno-fentry -mrecord-mcount -fno-pic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^(1|\t?\.)} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+**1: call mcount
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-5.c b/gcc/testsuite/gcc.target/i386/pr120936-5.c
new file mode 100644
index 0000000..20ecd37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -pg -mrecord-mcount -mno-fentry -fpic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^(1|\t?\.)} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+**1: call mcount@PLT
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-6.c b/gcc/testsuite/gcc.target/i386/pr120936-6.c
new file mode 100644
index 0000000..6e2290f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-6.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -mrecord-mcount -mnop-mcount -pg -mno-fentry -fno-pic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^(1|\t?\.)} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+**1: .byte 0x0f, 0x1f, 0x44, 0x00, 0x00
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-7.c b/gcc/testsuite/gcc.target/i386/pr120936-7.c
new file mode 100644
index 0000000..0c86467
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-7.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-options "-O2 -pg -mno-fentry -fpic -fno-plt -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+** call \*mcount@GOTPCREL\(%rip\)
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-8.c b/gcc/testsuite/gcc.target/i386/pr120936-8.c
new file mode 100644
index 0000000..3f86781
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-8.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-options "-O2 -pg -mrecord-mcount -mno-fentry -fpic -fno-plt -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^(1|\t?\.)} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+**1: call \*mcount@GOTPCREL\(%rip\)
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120936-9.c b/gcc/testsuite/gcc.target/i386/pr120936-9.c
new file mode 100644
index 0000000..3f4b387
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120936-9.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { fpic && lp64 } } } */
+/* { dg-options "-O2 -mcmodel=large -pg -mno-fentry -fno-pic -fno-shrink-wrap" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */
+
+/*
+**foo:
+**.LFB[0-9]+:
+**...
+** .cfi_.*
+** movabsq \$mcount, %r10
+** call \*%r10
+**...
+*/
+
+void
+foo (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-3.c b/gcc/testsuite/gcc.target/i386/pr93492-3.c
index b68da30..cdca595 100644
--- a/gcc/testsuite/gcc.target/i386/pr93492-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr93492-3.c
@@ -10,4 +10,4 @@ f10_endbr (void)
{
}
-/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n.*\.LPFE0:\n\tnop\n1:\tcall\t\[^\n\]*__fentry__\[^\n\]*\n\tret\n" } } */
+/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n.*\.LPFE0:\n\tnop\n\tcall\t\[^\n\]*__fentry__\[^\n\]*\n\tret\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-5.c b/gcc/testsuite/gcc.target/i386/pr93492-5.c
index ee9849a..cc71f67 100644
--- a/gcc/testsuite/gcc.target/i386/pr93492-5.c
+++ b/gcc/testsuite/gcc.target/i386/pr93492-5.c
@@ -9,4 +9,4 @@ foo (void)
{
}
-/* { dg-final { scan-assembler "\t\.cfi_startproc\n.*\.LPFE0:\n\tnop\n1:\tcall\t\[^\n\]*__fentry__\[^\n\]*\n\tret\n" } } */
+/* { dg-final { scan-assembler "\t\.cfi_startproc\n.*\.LPFE0:\n\tnop\n\tcall\t\[^\n\]*__fentry__\[^\n\]*\n\tret\n" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
index 6e97cae..84f013f 100644
--- a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
@@ -227,6 +227,18 @@ sat_s_add_imm_##T##_fmt_1##_##INDEX (T x) \
#define RUN_SAT_S_ADD_IMM_FMT_1(INDEX, T, x, expect) \
if (sat_s_add_imm##_##T##_fmt_1##_##INDEX(x) != expect) __builtin_abort ()
+#define DEF_SAT_S_ADD_IMM_FMT_2(INDEX, T, UT, IMM, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_add_imm_##T##_fmt_2##_##INDEX (T x) \
+{ \
+ T sum = (T)((UT)x + (UT)IMM); \
+ return ((x ^ sum) < 0 && (x ^ IMM) >= 0) ? \
+ (-(T)(x < 0) ^ MAX) : sum; \
+}
+
+#define RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect) \
+ if (sat_s_add_imm##_##T##_fmt_2##_##INDEX(x) != expect) __builtin_abort ()
+
/******************************************************************************/
/* Saturation Sub (Unsigned and Signed) */
/******************************************************************************/
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c
new file mode 100644
index 0000000..14c5d51
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int16_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*-7
+** xori\s+[atx][0-9]+,\s*a0,\s*-7
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*32768
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*16
+** sraiw\s+a0,\s*a0,\s*16
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int16_t, uint16_t, -7, INT16_MIN, INT16_MAX)
+
+/*
+** sat_s_add_imm_int16_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** not\s+[atx][0-9]+,\s*a0
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*32768
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*16
+** sraiw\s+a0,\s*a0,\s*16
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int16_t, uint16_t, -1, INT16_MIN, INT16_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c
new file mode 100644
index 0000000..ecd757d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int32_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*10
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*31
+** srli\s+[atx][0-9]+,\s*a0,\s*31
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-2147483648
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,a0,\s*[atx][0-9]+
+** sext.w\s+a0,\s*a0
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int32_t, uint32_t, 10, INT32_MIN, INT32_MAX)
+
+/*
+** sat_s_add_imm_int32_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** not\s+[atx][0-9]+,\s*a0
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*31
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*31
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-2147483648
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** sext.w\s+a0,\s*a0
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int32_t, uint32_t, -1, INT32_MIN, INT32_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c
new file mode 100644
index 0000000..07d798f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int64_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*10
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** srli\s+[atx][0-9]+,\s*a0,\s*63
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srai\s+[atx][0-9]+,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-1
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int64_t, uint64_t, 10, INT64_MIN, INT64_MAX)
+
+/*
+** sat_s_add_imm_int64_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** slti\s+[atx][0-9]+,\s*a0,\s*0
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srai\s+[atx][0-9]+,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-1
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int64_t, uint64_t, -1, INT64_MIN, INT64_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c
new file mode 100644
index 0000000..2734211
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int8_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*9
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*7
+** srli\s+[atx][0-9]+,\s*a0,\s*7
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** xori\s+[atx][0-9]+,\s*a0,\s*127
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*24
+** sraiw\s+a0,\s*a0,\s*24
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int8_t, uint8_t, 9, INT8_MIN, INT8_MAX)
+
+/*
+** sat_s_add_imm_int8_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*7
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srai\s+a0,\s*a0,\s*63
+** xori\s+[atx][0-9]+,\s*a0,\s*127
+** neg\s+a0,\s*a4
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*24
+** sraiw\s+a0,\s*a0,\s*24
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int8_t, uint8_t, -1, INT8_MIN, INT8_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c
new file mode 100644
index 0000000..4f24624
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int16_t, uint16_t, -32768, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int16_t, uint16_t, 32767, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int16_t, uint16_t, 100, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int16_t, uint16_t, -100, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int16_t, uint16_t, -1, INT16_MIN, INT16_MAX)
+
+#define T int16_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, -32768, },
+ { 2, -32766, },
+ { 1, 32767, },
+ { -10, 32757, },
+ { 32669, 32767, },
+ { -32768, -32668, },
+ { -32768, -32768, },
+ { 0, -100, },
+ { -32768, -32768, },
+ { 0, -1, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c
new file mode 100644
index 0000000..8d9ddeb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int32_t, uint32_t, -2147483648, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int32_t, uint32_t, 2147483647, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int32_t, uint32_t, 100, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int32_t, uint32_t, -100, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int32_t, uint32_t, -1, INT32_MIN, INT32_MAX)
+
+#define T int32_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, -2147483648, },
+ { 2, -2147483646, },
+ { 1, 2147483647, },
+ { -10, 2147483637, },
+ { 300, 400, },
+ { -300, -200, },
+ { 100, 0, },
+ { 0, -100, },
+ { 100, 99, },
+ { 0, -1, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c
new file mode 100644
index 0000000..4523f9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int64_t, uint64_t, (-9223372036854775807ll - 1), INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int64_t, uint64_t, 9223372036854775807ll, INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int64_t, uint64_t, 100, INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int64_t, uint64_t, -100, INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int64_t, uint64_t, -1, INT64_MIN, INT64_MAX)
+
+#define T int64_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, (-9223372036854775807ll - 1), },
+ { 2, -9223372036854775806ll, },
+ { 1, 9223372036854775807ll, },
+ { -7, 9223372036854775800ll, },
+ { 0, 100, },
+ { -1, 99, },
+ { 0, -100, },
+ { 100, 0, },
+ { 0, -1, },
+ { 100, 99, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c
new file mode 100644
index 0000000..96445ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int8_t, uint8_t, -128, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int8_t, uint8_t, 127, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int8_t, uint8_t, 6, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int8_t, uint8_t, -6, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int8_t, uint8_t, -1, INT8_MIN, INT8_MAX)
+
+#define T int8_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, -128, },
+ { 2, -126, },
+ { 1, 127, },
+ { -10, 117, },
+ { 122, 127, },
+ { -10, -4, },
+ { -128, -128, },
+ { 127, 121, },
+ { -128, -128, },
+ { 1, 0, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c
new file mode 100644
index 0000000..a73a77f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int16_t, uint16_t, -32769, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int16_t, uint16_t, 32768, INT16_MIN, INT16_MAX)
+
+/* { dg-final { scan-tree-dump-not ".SAT_ADD " "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c
new file mode 100644
index 0000000..9dae425
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_1(0, int32_t, uint32_t, -2147483649, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_1(1, int32_t, uint32_t, 2147483648, INT32_MIN, INT32_MAX)
+
+/* { dg-final { scan-tree-dump-not ".SAT_ADD " "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c
new file mode 100644
index 0000000..a9cd4b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int8_t, uint8_t, -129, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int8_t, uint8_t, 128, INT8_MIN, INT8_MAX)
+
+/* { dg-final { scan-tree-dump-not ".SAT_ADD " "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-perm-merge-1.c b/gcc/testsuite/gcc.target/s390/vector/vec-perm-merge-1.c
new file mode 100644
index 0000000..79f8a88
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/vec-perm-merge-1.c
@@ -0,0 +1,242 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -march=z14 -mzvector --save-temps -fno-stack-protector" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+/* { dg-final {check-function-bodies "**" "" } } */
+
+#include "vec-types.h"
+
+/*
+** qi_via_hi_hi:
+** vmrhh %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_hi_hi (v16qi a, v16qi b)
+{
+ return (v16qi){a[0], a[1], b[0], b[1], a[2], a[3], b[2], b[3],
+ a[4], a[5], b[4], b[5], a[6], a[7], b[6], b[7]};
+}
+
+/*
+** qi_via_hi_lo:
+** vmrlh %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_hi_lo (v16qi a, v16qi b)
+{
+ return (v16qi){a[8], a[9], b[8], b[9], a[10], a[11], b[10], b[11],
+ a[12], a[13], b[12], b[13], a[14], a[15], b[14], b[15]};
+}
+
+/*
+** qi_via_si_hi:
+** vmrhf %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_si_hi (v16qi a, v16qi b)
+{
+ return (v16qi){a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3],
+ a[4], a[5], a[6], a[7], b[4], b[5], b[6], b[7]};
+}
+
+/*
+** qi_via_si_lo:
+** vmrlf %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_si_lo (v16qi a, v16qi b)
+{
+ return (v16qi){a[8], a[9], a[10], a[11], b[8], b[9], b[10], b[11],
+ a[12], a[13], a[14], a[15], b[12], b[13], b[14], b[15]};
+}
+
+/*
+** qi_via_di_hi:
+** vmrhg %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_di_hi (v16qi a, v16qi b)
+{
+ return (v16qi){a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
+ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]};
+}
+
+/*
+** qi_via_di_lo:
+** vmrlg %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_di_lo (v16qi a, v16qi b)
+{
+ return (v16qi){a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15],
+ b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]};
+}
+
+/*
+** hi_via_si_hi:
+** vmrhf %v24,%v24,%v26
+** br %r14
+*/
+v8hi __attribute__((noinline,noipa))
+hi_via_si_hi (v8hi a, v8hi b)
+{
+ return (v8hi){a[0], a[1], b[0], b[1], a[2], a[3], b[2], b[3]};
+}
+
+/*
+** hi_via_si_lo:
+** vmrlf %v24,%v24,%v26
+** br %r14
+*/
+v8hi __attribute__((noinline,noipa))
+hi_via_si_lo (v8hi a, v8hi b)
+{
+ return (v8hi){a[4], a[5], b[4], b[5], a[6], a[7], b[6], b[7]};
+}
+
+/*
+** hi_via_di_hi:
+** vmrhg %v24,%v24,%v26
+** br %r14
+*/
+v8hi __attribute__((noinline,noipa))
+hi_via_di_hi (v8hi a, v8hi b)
+{
+ return (v8hi){a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]};
+}
+
+/*
+** hi_via_di_lo:
+** vmrlg %v24,%v24,%v26
+** br %r14
+*/
+v8hi __attribute__((noinline,noipa))
+hi_via_di_lo (v8hi a, v8hi b)
+{
+ return (v8hi){a[4], a[5], a[6], a[7], b[4], b[5], b[6], b[7]};
+}
+
+/*
+** si_via_di_hi:
+** vmrhg %v24,%v24,%v26
+** br %r14
+*/
+v4si __attribute__((noinline,noipa))
+si_via_di_hi (v4si a, v4si b)
+{
+ return (v4si){a[0], a[1], b[0], b[1]};
+}
+
+/*
+** si_via_di_lo:
+** vmrlg %v24,%v24,%v26
+** br %r14
+*/
+v4si __attribute__((noinline,noipa))
+si_via_di_lo (v4si a, v4si b)
+{
+ return (v4si){a[2], a[3], b[2], b[3]};
+}
+
+int
+main ()
+{
+ static const signed char e_qi_via_hi_hi[16]
+ = {0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23};
+ static const signed char e_qi_via_hi_lo[16]
+ = {8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31};
+ static const signed char e_qi_via_si_hi[16]
+ = {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23};
+ static const signed char e_qi_via_si_lo[16]
+ = {8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31};
+ static const signed char e_qi_via_di_hi[16]
+ = {0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23};
+ static const signed char e_qi_via_di_lo[16]
+ = {8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31};
+
+ static const short e_hi_via_si_hi[8] = {0, 1, 8, 9, 2, 3, 10, 11};
+ static const short e_hi_via_si_lo[8] = {4, 5, 12, 13, 6, 7, 14, 15};
+ static const short e_hi_via_di_hi[8] = {0, 1, 2, 3, 8, 9, 10, 11};
+ static const short e_hi_via_di_lo[8] = {4, 5, 6, 7, 12, 13, 14, 15};
+
+ static const int e_si_via_di_hi[4] = {0, 1, 4, 5};
+ static const int e_si_via_di_lo[4] = {2, 3, 6, 7};
+
+ v16qi a_qi = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ v16qi b_qi = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
+ v8hi a_hi = {0, 1, 2, 3, 4, 5, 6, 7};
+ v8hi b_hi = {8, 9, 10, 11, 12, 13, 14, 15};
+ v4si a_si = {0, 1, 2, 3};
+ v4si b_si = {4, 5, 6, 7};
+ v16qi r_qi;
+ v8hi r_hi;
+ v4si r_si;
+ int i;
+
+ r_qi = qi_via_hi_hi (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_hi_hi[i])
+ __builtin_abort ();
+
+ r_qi = qi_via_hi_lo (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_hi_lo[i])
+ __builtin_abort ();
+
+ r_qi = qi_via_si_hi (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_si_hi[i])
+ __builtin_abort ();
+
+ r_qi = qi_via_si_lo (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_si_lo[i])
+ __builtin_abort ();
+
+ r_qi = qi_via_di_hi (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_di_hi[i])
+ __builtin_abort ();
+
+ r_qi = qi_via_di_lo (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_di_lo[i])
+ __builtin_abort ();
+
+ r_hi = hi_via_si_hi (a_hi, b_hi);
+ for (i = 0; i < 8; ++i)
+ if (r_hi[i] != e_hi_via_si_hi[i])
+ __builtin_abort ();
+
+ r_hi = hi_via_si_lo (a_hi, b_hi);
+ for (i = 0; i < 8; ++i)
+ if (r_hi[i] != e_hi_via_si_lo[i])
+ __builtin_abort ();
+
+ r_hi = hi_via_di_hi (a_hi, b_hi);
+ for (i = 0; i < 8; ++i)
+ if (r_hi[i] != e_hi_via_di_hi[i])
+ __builtin_abort ();
+
+ r_hi = hi_via_di_lo (a_hi, b_hi);
+ for (i = 0; i < 8; ++i)
+ if (r_hi[i] != e_hi_via_di_lo[i])
+ __builtin_abort ();
+
+ r_si = si_via_di_hi (a_si, b_si);
+ for (i = 0; i < 4; ++i)
+ if (r_si[i] != e_si_via_di_hi[i])
+ __builtin_abort ();
+
+ r_si = si_via_di_lo (a_si, b_si);
+ for (i = 0; i < 4; ++i)
+ if (r_si[i] != e_si_via_di_lo[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-perm-pack-1.c b/gcc/testsuite/gcc.target/s390/vector/vec-perm-pack-1.c
new file mode 100644
index 0000000..6590c92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/vec-perm-pack-1.c
@@ -0,0 +1,133 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -march=z14 -mzvector --save-temps -fno-stack-protector" } */
+/* { dg-do run { target { s390_z14_hw } } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "vec-types.h"
+
+/*
+** qi_via_hi:
+** vpkh %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_hi (v16qi a, v16qi b)
+{
+ return (v16qi){a[1], a[3], a[5], a[7], a[9], a[11], a[13], a[15],
+ b[1], b[3], b[5], b[7], b[9], b[11], b[13], b[15]};
+}
+
+/*
+** qi_via_si:
+** vpkf %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_si (v16qi a, v16qi b)
+{
+ return (v16qi){a[2], a[3], a[6], a[7], a[10], a[11], a[14], a[15],
+ b[2], b[3], b[6], b[7], b[10], b[11], b[14], b[15]};
+}
+
+/*
+** qi_via_di:
+** vpkg %v24,%v24,%v26
+** br %r14
+*/
+v16qi __attribute__((noinline,noipa))
+qi_via_di (v16qi a, v16qi b)
+{
+ return (v16qi){a[4], a[5], a[6], a[7], a[12], a[13], a[14], a[15],
+ b[4], b[5], b[6], b[7], b[12], b[13], b[14], b[15]};
+}
+
+/*
+** hi_via_si:
+** vpkf %v24,%v24,%v26
+** br %r14
+*/
+v8hi __attribute__((noinline,noipa))
+hi_via_si (v8hi a, v8hi b)
+{
+ return (v8hi){a[1], a[3], a[5], a[7], b[1], b[3], b[5], b[7]};
+}
+
+/*
+** hi_via_di:
+** vpkg %v24,%v24,%v26
+** br %r14
+*/
+v8hi __attribute__((noinline,noipa))
+hi_via_di (v8hi a, v8hi b)
+{
+ return (v8hi){a[2], a[3], a[6], a[7], b[2], b[3], b[6], b[7]};
+}
+
+/*
+** si_via_di:
+** vpkg %v24,%v24,%v26
+** br %r14
+*/
+v4si __attribute__((noinline,noipa))
+si_via_di (v4si a, v4si b)
+{
+ return (v4si){a[1], a[3], b[1], b[3]};
+}
+
+int
+main ()
+{
+ static const signed char e_qi_via_hi[16]
+ = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31};
+ static const signed char e_qi_via_si[16]
+ = {2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31};
+ static const signed char e_qi_via_di[16]
+ = {4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31};
+
+ static const short e_hi_via_si[8] = {1, 3, 5, 7, 9, 11, 13, 15};
+ static const short e_hi_via_di[8] = {2, 3, 6, 7, 10, 11, 14, 15};
+
+ static const int e_si_via_di[4] = {1, 3, 5, 7};
+
+ v16qi a_qi = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ v16qi b_qi = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
+ v8hi a_hi = {0, 1, 2, 3, 4, 5, 6, 7};
+ v8hi b_hi = {8, 9, 10, 11, 12, 13, 14, 15};
+ v4si a_si = {0, 1, 2, 3};
+ v4si b_si = {4, 5, 6, 7};
+ v16qi r_qi;
+ v8hi r_hi;
+ v4si r_si;
+ int i;
+
+ r_qi = qi_via_hi (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_hi[i])
+ __builtin_abort ();
+
+ r_qi = qi_via_si (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_si[i])
+ __builtin_abort ();
+
+ r_qi = qi_via_di (a_qi, b_qi);
+ for (i = 0; i < 16; ++i)
+ if (r_qi[i] != e_qi_via_di[i])
+ __builtin_abort ();
+
+ r_hi = hi_via_si (a_hi, b_hi);
+ for (i = 0; i < 8; ++i)
+ if (r_hi[i] != e_hi_via_si[i])
+ __builtin_abort ();
+
+ r_hi = hi_via_di (a_hi, b_hi);
+ for (i = 0; i < 8; ++i)
+ if (r_hi[i] != e_hi_via_di[i])
+ __builtin_abort ();
+
+ r_si = si_via_di (a_si, b_si);
+ for (i = 0; i < 4; ++i)
+ if (r_si[i] != e_si_via_di[i])
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/gomp/omp_get_num_devices_initial_device.f90 b/gcc/testsuite/gfortran.dg/gomp/omp_get_num_devices_initial_device.f90
index 5409f12..279656b 100644
--- a/gcc/testsuite/gfortran.dg/gomp/omp_get_num_devices_initial_device.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/omp_get_num_devices_initial_device.f90
@@ -17,8 +17,8 @@ end
! { dg-final { scan-tree-dump-not "error_stop" "optimized" } }
-! { dg-final { scan-tree-dump-not "omp_get_num_devices;" "optimized" { target { ! offloading_enabled } } } }
+! { dg-final { scan-tree-dump-not "omp_get_num_devices" "optimized" { target { ! offloading_enabled } } } }
! { dg-final { scan-tree-dump "return 0;" "optimized" { target { ! offloading_enabled } } } }
-! { dg-final { scan-tree-dump-times "omp_get_num_devices;" 1 "optimized" { target offloading_enabled } } }
+! { dg-final { scan-tree-dump-times "omp_get_num_devices" 1 "optimized" { target offloading_enabled } } }
! { dg-final { scan-tree-dump "_1 = __builtin_omp_get_num_devices \\(\\);\[\\r\\n\]+\[ \]+return _1;" "optimized" { target offloading_enabled } } }
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 25ceeea..956bc0b 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -12460,12 +12460,14 @@ proc check_effective_target_aarch64_gas_has_build_attributes { } {
# Create functions to check that the AArch64 assembler supports the
# various architecture extensions via the .arch_extension pseudo-op.
-foreach { aarch64_ext } { "fp" "simd" "crypto" "crc" "lse" "dotprod" "sve"
- "i8mm" "f32mm" "f64mm" "bf16" "sb" "sve2" "ls64"
- "lut" "sme" "sme-i16i64" "sme2" "sve-b16b16"
- "sme-b16b16" "sme-f16f16" "sme2p1" "fp8" "fp8fma"
- "ssve-fp8fma" "fp8dot2" "ssve-fp8dot2" "fp8dot4"
- "ssve-fp8dot4"} {
+set exts {
+ "bf16" "cmpbr" "crc" "crypto" "dotprod" "f32mm" "f64mm" "fp" "fp8"
+ "fp8dot2" "fp8dot4" "fp8fma" "i8mm" "ls64" "lse" "lut" "sb" "simd"
+ "sme-b16b16" "sme-f16f16" "sme-i16i64" "sme" "sme2" "sme2p1" "ssve-fp8dot2"
+ "ssve-fp8dot4" "ssve-fp8fma" "sve-b16b16" "sve" "sve2"
+}
+
+foreach { aarch64_ext } $exts {
eval [string map [list FUNC $aarch64_ext] {
proc check_effective_target_aarch64_asm_FUNC_ok { } {
if { [istarget aarch64*-*-*] } {
diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
index ec4419f..a551f2b 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -464,6 +464,93 @@ compute_object_offset (tree expr, const_tree var)
return size_binop (code, base, off);
}
+/* Return true if CONTAINER has a field of type INNER at OFFSET. */
+
+static bool
+inner_at_offset (tree container, tree inner, tree offset)
+{
+ gcc_assert (RECORD_OR_UNION_TYPE_P (container));
+
+ for (tree t = TYPE_FIELDS (container); t; t = DECL_CHAIN (t))
+ {
+ if (TREE_CODE (t) != FIELD_DECL)
+ continue;
+
+ /* Skip over fields at bit offsets that are not BITS_PER_UNIT aligned
+ to avoid an accidental truncated match with BYTE_POSITION below since
+ the address of such fields cannot be taken. */
+ if (wi::bit_and (wi::to_offset (DECL_FIELD_BIT_OFFSET (t)),
+ BITS_PER_UNIT - 1) != 0)
+ continue;
+
+ tree byte_offset = byte_position (t);
+ if (TREE_CODE (byte_offset) != INTEGER_CST
+ || tree_int_cst_lt (offset, byte_offset))
+ return false;
+
+ /* For an array, check the element type, otherwise the actual type. This
+ deliberately does not support the case of jumping from a pointer to
+ the middle of an array to its containing struct. */
+ tree t_type = TREE_TYPE (t);
+ if (((TREE_CODE (t_type) == ARRAY_TYPE && TREE_TYPE (t_type) == inner)
+ || t_type == inner)
+ && tree_int_cst_equal (byte_offset, offset))
+ return true;
+
+ /* Nested structure or union, adjust the expected offset and dive in. */
+ if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
+ && inner_at_offset (TREE_TYPE (t), inner,
+ fold_build2 (MINUS_EXPR, sizetype, offset,
+ byte_offset)))
+ return true;
+ }
+
+ return false;
+}
+
+/* For the input MEMREF of type MEMREF_TYPE, look for the presence of a field
+ of BASE_TYPE at OFFSET and return an adjusted WHOLESIZE if found. */
+
+static tree
+get_wholesize_for_memref (tree memref, tree wholesize)
+{
+ tree base = TREE_OPERAND (memref, 0);
+ tree offset = fold_convert (sizetype, TREE_OPERAND (memref, 1));
+ tree memref_type = TREE_TYPE (memref);
+ tree base_type = TREE_TYPE (base);
+
+ if (POINTER_TYPE_P (base_type))
+ base_type = TREE_TYPE ((base_type));
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "wholesize_for_memref: ");
+ print_generic_expr (dump_file, wholesize, dump_flags);
+ fprintf (dump_file, ", offset: ");
+ print_generic_expr (dump_file, offset, dump_flags);
+ fprintf (dump_file, "\n");
+ }
+
+ if (TREE_CODE (offset) != INTEGER_CST
+ || compare_tree_int (offset, offset_limit) < 0
+ || !RECORD_OR_UNION_TYPE_P (memref_type))
+ return wholesize;
+
+ offset = fold_build1 (NEGATE_EXPR, sizetype, offset);
+
+ if (inner_at_offset (memref_type, base_type, offset))
+ wholesize = size_binop (PLUS_EXPR, wholesize, offset);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, " new wholesize: ");
+ print_generic_expr (dump_file, wholesize, dump_flags);
+ fprintf (dump_file, "\n");
+ }
+
+ return wholesize;
+}
+
/* Returns the size of the object designated by DECL considering its
initializer if it either has one or if it would not affect its size,
otherwise the size of the object without the initializer when MIN
@@ -536,7 +623,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
{
compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
object_size_type & ~OST_SUBOBJECT, &sz);
- wholesize = sz;
+ wholesize = get_wholesize_for_memref (pt_var, sz);
}
else
{
@@ -548,6 +635,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
{
sz = object_sizes_get (osi, SSA_NAME_VERSION (var));
wholesize = object_sizes_get (osi, SSA_NAME_VERSION (var), true);
+ wholesize = get_wholesize_for_memref (pt_var, wholesize);
}
else
sz = wholesize = size_unknown (object_size_type);