diff options
31 files changed, 831 insertions, 198 deletions
@@ -1,3 +1,7 @@ +2025-07-22 Patrick Palka <ppalka@redhat.com> + + * MAINTAINERS: Add myself as C++ front end reviewer. + 2025-07-07 Tamar Christina <tamar.christina@arm.com> * MAINTAINERS: Add myself to AArch64 pot. diff --git a/MAINTAINERS b/MAINTAINERS index 2cd2ec6..d4ed308 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -282,6 +282,7 @@ callgraph Martin Jambor <mjambor@suse.cz> C front end Marek Polacek <polacek@redhat.com> CTF, BTF Indu Bhagat <indu.bhagat@oracle.com> CTF, BTF, bpf port David Faust <david.faust@oracle.com> +c++ Patrick Palka <ppalka@gcc.gnu.org> dataflow Paolo Bonzini <bonzini@gnu.org> dataflow Seongbae Park <seongbae.park@gmail.com> dataflow Kenneth Zadeck <zadeck@naturalbridge.com> diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f3e4ba1..6276e83 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,52 @@ +2025-07-22 Andrew Pinski <quic_apinski@quicinc.com> + + PR middle-end/109267 + * tree-cfgcleanup.cc (execute_cleanup_cfg_post_optimizing): If the first + non debug statement in the first (and only) basic block is a call + to __builtin_unreachable change it to a call to __builtin_trap or an + infinite loop. + +2025-07-22 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * config/xtensa/xtensa.cc (xtensa_is_insn_L32R_p): + Rewrite to capture insns that could be L32R machine instructions + wherever possible. + (xtensa_rtx_costs): Fix to consider that moves larger than a + natural word can take multiple L32R machine instructions. + (constantpool_address_p): Cosmetics. + * config/xtensa/xtensa.md (movdi_internal, movdf_internal): + Add missing insn attributes. + +2025-07-22 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * config/xtensa/xtensa.md + (movsi_internal, movhi_internal, movsf_internal): + Change the value of the "type" attribute from "move" to "load" + when the source operand constraint is "Y". + +2025-07-22 Karl Meakin <karl.meakin@arm.com> + + * tree-vect-data-refs.cc (vect_check_gather_scatter): Swap + `base` and `off` in more scenarios. Also assert at the end of + the function that `base` and `off` are loop-invariant and not + loop-invariant respectively. + +2025-07-22 Jeff Law <jlaw@ventanamicro.com> + + * config/riscv/generic-vector-ooo.md: Restrict insn reservations to + generic_ooo and generic tuning models. + +2025-07-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/121202 + * tree-vect-slp.cc (vect_schedule_slp_node): Do not take + an out-of-region stmt as "last". + +2025-07-22 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + * genpreds.cc (write_insn_constraint_len): Replace rawmemchr by + a loop. + 2025-07-21 Jeff Law <jlaw@ventanamicro.com> * config/riscv/mips-p8700.md: Add support for "ghost" insn types. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7578d89..bd609e4 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250722 +20250723 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d1b78d4..fda0dd5 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,275 @@ +2025-07-22 Gary Dismukes <dismukes@adacore.com> + + * sem_ch8.adb (End_Use_Type): Add a test for there not being an earlier + use_type_clause for the same type as an additional criterion for turning + off In_Use and Current_Use_Clause. + +2025-07-22 Piotr Trojanek <trojanek@adacore.com> + + * sem_attr.adb (Eval_Attribute): Only fold array attributes when prefix + is static or at least safe to evaluate + +2025-07-22 Ronan Desplanques <desplanques@adacore.com> + + * einfo.ads (Is_Controlled_Active): Fix pasto in comment. + * sem_util.ads (Propagate_Controlled_Flags): Update comment for + Destructor aspect. + +2025-07-22 Ronan Desplanques <desplanques@adacore.com> + + * doc/gnat_rm/gnat_language_extensions.rst: Document new extension. + * snames.ads-tmpl: Add name for new aspect. + * gen_il-fields.ads (Has_Destructor, Is_Destructor): Add new fields. + * gen_il-gen-gen_entities.adb (E_Procedure, Type_Kind): Add new fields. + * einfo.ads (Has_Destructor, Is_Destructor): Document new fields. + * aspects.ads: Add new aspect. + * sem_ch13.adb (Analyze_Aspect_Specifications, + Check_Aspect_At_Freeze_Point, Check_Aspect_At_End_Of_Declarations): + Add semantic analysis for new aspect. + (Resolve_Finalization_Procedure): New function. + (Resolve_Finalizable_Argument): Use new function above. + * sem_util.adb (Propagate_Controlled_Flags): Extend for new field. + * freeze.adb (Freeze_Entity): Add legality check for new aspect. + * exp_ch3.adb (Expand_Freeze_Record_Type, Predefined_Primitive_Bodies): + Use new field. + * exp_ch7.adb (Build_Finalize_Statements): Add expansion for + destructors. + (Make_Final_Call, Build_Record_Deep_Procs): Adapt to new Has_Destructor + field. + (Build_Adjust_Statements): Tweak to handle cases of empty lists. + * gnat_rm.texi: Regenerate. + +2025-07-22 Denis Mazzucato <mazzucato@adacore.com> + + * sem_ch6.adb (Might_Need_BIP_Task_Actuals): Before retrieving the original corresponding + operation we retrieve first the root of the aliased chain. + +2025-07-22 Ronan Desplanques <desplanques@adacore.com> + + * gen_il-fields.ads (Is_Implicit_Full_View): New field. + * gen_il-gen-gen_entities.adb (Type_Kind): Use new field. + * einfo.ads (Is_Implicit_Full_View): Document new field. + * exp_ch7.adb (Make_Adjust_Call, Make_Init_Call, Make_Final_Call): Use + new field. + * exp_util.adb (Finalize_Address): Likewise. + * sem_ch3.adb (Copy_And_Build): Set new field. + +2025-07-22 Eric Botcazou <ebotcazou@adacore.com> + + * exp_util.ads (May_Generate_Large_Temp): Delete. + * exp_util.adb (May_Generate_Large_Temp): Likewise. + (Safe_Unchecked_Type_Conversion): Do not take stack checking into + account to compute the result. + +2025-07-22 Javier Miranda <miranda@adacore.com> + + * sinfo.ads (Is_Expanded_Dispatching_Call): New flag. + (Tag_Propagated): New flag. + * exp_ch6.adb (Expand_Call_Helper): Propagate the tag when + the dispatching call is placed in conditionl expressions or + case-expressions. + * sem_ch5.adb (Analyze_Assignment): For assignment of tag- + indeterminate expression, do not propagate the tag if + previously done. + * sem_disp.adb (Is_Tag_Indeterminate): Add missing support + for conditional expression and case expression. + * exp_disp.ads (Is_Expanded_Dispatching_Call): Removed. Function + replaced by a new flag in the nodes. + * exp_disp.adb (Expand_Dispatching_Call): Set a flag in the + call node to remember that the call has been expanded. + (Is_Expanded_Dispatching_Call): Function removed. + * gen_il-fields.ads (Tag_Propagated): New flag. + (Is_Expanded_Dispatching_Call): New flag. + * gen_il-gen-gen_nodes.adb (Tag_Propagated): New flag. + (Is_Expanded_Dispatching_Call): New flag. + +2025-07-22 Gary Dismukes <dismukes@adacore.com> + + * libgnat/a-cbhama.ads (Empty): Add missing default to Capacity formal. + * libgnat/a-cbhama.adb (Empty): Add missing default to Capacity formal. + * exp_aggr.adb (Build_Size_Expr): Test for presence of Capacity + discriminant as additional criterion for generating the call to + the Length function. Update comments. + +2025-07-22 Eric Botcazou <ebotcazou@adacore.com> + + * exp_util.adb (Safe_Unchecked_Type_Conversion): Always return True + if the expression is the prefix of an N_Selected_Component. + +2025-07-22 Denis Mazzucato <mazzucato@adacore.com> + + * sem_ch6.adb (Might_Need_BIP_Task_Actuals): Check whether No_Task_Parts is enabled in any + of the derived types, or interfaces, from the user-defined primitive return type. + * sem_ch13.adb (Analyze_Aspect_Specifications): Add No_Task_Parts and No_Controlled_Parts to + the representation chain to be visible in the full view of private types. + * aspects.ads (Nonoverridable_Aspect_Id): As per GNAT RM, No_Task_Parts is nonoverridable. + * sem_util.adb (Check_Inherited_Nonoverridable_Aspects): Likewise. + * sem_util.ads: Fix typo and style. + * sem_disp.adb: Missing comment. + +2025-07-22 Javier Miranda <miranda@adacore.com> + + * einfo.ads (Extra_Formals): Complete documentation. + (Has_First_Controlling_Parameter_Aspect): Place it in alphabetical order. + (Has_Frozen_Extra_Formals): New attribute. + * gen_il-fields.ads (Has_Frozen_Extra_Formals): New entity field. + * gen_il-gen-gen_entities.adb (Has_Frozen_Extra_Formals): Adding new + entity flag to subprograms, subprogram types, and and entries. + * gen_il-internals.adb (Image): Adding Has_Frozen_Extra_Formals. + * exp_ch3.adb (Build_Array_Init_Proc): Freeze its extra formals. + (Build_Init_Procedure): Freeze its extra formals. + (Expand_Freeze_Record_Type): For tagged types with foreign convention + create the extra formals of primitives with convention Ada. + * exp_ch6.ads (Create_Extra_Actuals): New subprogram. + * exp_ch6.adb (Check_BIP_Actuals): Adding assertions. + (Create_Extra_Actuals): New subprogram that factorizes code from + Expand_Call_Helper. + (Expand_Call_Helper): Adding support to defer the addition of extra + actuals. Move the code that adds the extra actuals to a new subprogram. + (Is_Unchecked_Union_Equality): Renamed as Is_Unchecked_Union_Predefined_ + Equality_Call. + * exp_ch7.adb (Create_Finalizer): Freeze its extra formals. + (Wrap_Transient_Expression): Link the temporary with its relocated + expression to facilitate locating the expression in the expanded code. + * exp_ch9.ads (Expand_N_Entry_Declaration): Adding one formal. + * exp_ch9.adb (Expand_N_Entry_Declaration): Defer the expansion of + the entry if the extra formals are not available; analyze the built + declarations for the record type that holds all the parameters if + the expansion of the entry declaration was deferred. + * exp_disp.adb (Expand_Dispatching_Call): Handle deferred extra formals. + (Set_CPP_Constructors): Freeze its extra formals. + * freeze.adb (Freeze_Entity): Create the extra actuals of acccess to + subprograms whose designated type is a subprogram type. + (Freeze_Subprogram): Adjust assertion to support deferred extra formals, + and freeze extra formals of non-dispatching subprograms with foreign + convention. Added assertion to check matching of formals in thunks. + * sem_aux.adb (Get_Called_Entity): Adding documentation. + * sem_ch3.adb (Analyze_Full_Type_Declaration): Create the extra formals + of deferred subprograms, subprogram types and entries; create also the + extra actuals of deferred calls. + * sem_ch6.ads (Freeze_Extra_Formals): New subprogram. + (Deferred_Extra_Formals_Support): New package. + * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Create the extra formals + of subprograms without separate spec. + (Add_Extra_Formal): Add documentation. + (Has_Extra_Formals): Removed. + (Parent_Subprogram): Adding documentation. + (Create_Extra_Formals): Defer adding extra formals if the underlying_type + of some formal type or return type is not available. + (Extra_Formals_Match_OK): Add missing check on the extra formals of + unchecked unions. + (Freeze_Extra_Formals): New subprogram. + (Deferred_Extra_Formals_Support): New package. + * sem_ch9.adb (Analyze_Entry_Declaration): Freeze its extra formals. + * sem_ch13.adb (New_Put_Image_Subprogram): ditto. + * sem_util.ads (Is_Unchecked_Union_Equality): New subprogram. + * sem_util.adb (Is_Unchecked_Union_Equality): ditto. + +2025-07-22 Piotr Trojanek <trojanek@adacore.com> + + * sem_util.adb (Get_Actual_Subtype): Do the same for GCC and GNATprove + backends. + +2025-07-22 Martin Clochard <clochard@adacore.com> + + * exp_spark.adb (Expand_SPARK): Add expansion of continue statements. + (Expand_SPARK_N_Continue_Statement): Expand continue statements resolved + as procedure calls into said procedure calls. + +2025-07-22 Piotr Trojanek <trojanek@adacore.com> + + * sem_res.adb (Resolve_Call): Look at the base type of actual parameter + when checking call to Set_Handler. + +2025-07-22 Eric Botcazou <ebotcazou@adacore.com> + + * sem_util.adb (Get_Actual_Subtype): Only create a new subtype when + the expander is active. Remove a useless test of type inequality, + as well as a useless call to Set_Has_Delayed_Freeze on the subtype. + +2025-07-22 Gary Dismukes <dismukes@adacore.com> + + * exp_aggr.adb (Build_Size_Expr): Change test of "not Present (...)" + to "No (...)". + +2025-07-22 Gary Dismukes <dismukes@adacore.com> + + * exp_aggr.adb (Build_Size_Expr): Determine the length of a container + aggregate association in the case where it's an iteration over an + object of a container type coming from an instantiation of a predefined + container generic. Minor updates to existing comments. + +2025-07-22 Ghjuvan Lacambre <lacambre@adacore.com> + + * exp_util.adb (Finalize_Address): Prevent infinite loop + +2025-07-22 Steve Baird <baird@adacore.com> + + * sem_aux.ads: Declare new function Unique_Component_Name. + * sem_aux.adb: Implement new function Unique_Component_Name. + +2025-07-22 Viljar Indus <indus@adacore.com> + + * sem_ch13.adb (Check_Aspect_At_End_Of_Declarations): + Ensure the Expression_Copy always has a parent before + calling any analyze. + +2025-07-22 Steve Baird <baird@adacore.com> + + * exp_aggr.adb (Build_Record_Aggr_Code.Gen_Assign): In the case of + an aggregate component where the component type is mutably tagged + and the component value is provided by a qualified aggregate (and + qualified with a specific type), avoid incorrectly rejecting the + inner aggregate for violating the rule that the type of an + aggregate shall not be class-wide. + * exp_attr.adb: For a predefined streaming operation (i.e., Read, + Write, Input, or Output) of a class-wide type, the external name + of the tag of the value is normally written out by Output and read + in by Input. In the case of a mutably tagged type, this is instead + done in Write and Read. + * exp_ch4.adb (Expand_Composite_Equality): In the case of an + equality comparison for a type having a mutably tagged component, + we want the component comparison to compare two values of the + mutably tagged type, not two values of the corresponding + array-of-bytes-ish representation type. Even if there are no + user-defined equality functions anywhere in sight, comparing the + array values still doesn't work because undefined bits may end up + participating in the comparison (resulting in an incorrect result + of False). + * exp_put_image.adb: In the case of a class-wide type, the + predefined Image attribute includes the name of the specific type + (and a "'" character, to follow qualified expression syntax) to + indicate the tag of the value. With the introduction of mutably + tagged types, this case can now arise in the case of a component + (of either an enclosing array or an enclosing record), not just + for a top-level object. So we factor the code to do this into a + new procedure, Put_Specific_Type_Name_Qualifier, so that it can be + called from more than one place. This reorganization also involves + replacing the procedure Put_String_Exp with a new procedure, + Put_String_Exp_To_Buffer, declared in a less nested scope. For + mutably tagged components (at the source level) the component type + (at the GNAT tree level) is an array of bytes (actually a two + field record containing an array of bytes, but that's a detail). + Appropriate conversions need to be generated so that we don't end + up generating an image for an array of bytes; this is done at the + same places where Put_Specific_Type_Name_Qualifier is called + (for components) by calling Make_Mutably_Tagged_Conversion. + * exp_strm.adb (Make_Field_Attribute): Add + Make_Mutably_Tagged_Conversion call where we construct a + Selected_Component node and the corresponding component type is + the internal representation type for a mutably tagged type. + (Stream_Base_Type): Return the mutably + tagged type if given the corresponding internal representation type. + * sem_ch3.adb (Array_Type_Declaration): In the case where the + source-level component type of an array type is mutably tagged, + set the Component_Type field of the base type of the declared + array type (as opposed to that of the first subtype of the array + type) to the corresponding internal representation type. + * sem_ch4.adb (Analyze_Selected_Component): In the case of a + selected component name which references a component whose type is + the internal representation type of a mutably tagged type, + generate a conversion to the mutably tagged type. + 2025-07-21 Eric Botcazou <ebotcazou@gcc.gnu.org> PR ada/121184 diff --git a/gcc/config/riscv/generic-vector-ooo.md b/gcc/config/riscv/generic-vector-ooo.md index ab9e57f..773003b 100644 --- a/gcc/config/riscv/generic-vector-ooo.md +++ b/gcc/config/riscv/generic-vector-ooo.md @@ -17,6 +17,9 @@ ;; <http://www.gnu.org/licenses/>. ;; Vector load/store +;; The insn reservations include "generic" as we won't have a in-order +;; generic definition for vector instructions. + (define_automaton "vector_ooo") ;; Separate issue queue for vector instructions. @@ -29,119 +32,141 @@ (define_cpu_unit "vxu_ooo_multicycle" "vector_ooo") (define_insn_reservation "vec_load" 6 - (eq_attr "type" "vlde,vldm,vlds,vldux,vldox,vldff,vldr") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vlde,vldm,vlds,vldux,vldox,vldff,vldr")) "vxu_ooo_issue,vxu_ooo_alu") (define_insn_reservation "vec_store" 6 - (eq_attr "type" "vste,vstm,vsts,vstux,vstox,vstr") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vste,vstm,vsts,vstux,vstox,vstr")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector segment loads/stores. (define_insn_reservation "vec_loadstore_seg" 10 - (eq_attr "type" "vlsegde,vlsegds,vlsegdux,vlsegdox,vlsegdff,\ - vssegte,vssegts,vssegtux,vssegtox") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vlsegde,vlsegds,vlsegdux,vlsegdox,vlsegdff,\ + vssegte,vssegts,vssegtux,vssegtox")) "vxu_ooo_issue,vxu_ooo_alu") ;; Regular vector operations and integer comparisons. (define_insn_reservation "vec_alu" 3 - (eq_attr "type" "vialu,viwalu,vext,vicalu,vshift,vnshift,viminmax,vicmp,\ - vimov,vsalu,vaalu,vsshift,vnclip,vmov,vfmov,vector,\ - vandn,vbrev,vbrev8,vrev8,vclz,vctz,vrol,vror,vwsll") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vialu,viwalu,vext,vicalu,vshift,vnshift,viminmax,vicmp,\ + vimov,vsalu,vaalu,vsshift,vnclip,vmov,vfmov,vector,\ + vandn,vbrev,vbrev8,vrev8,vclz,vctz,vrol,vror,vwsll")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector float comparison, conversion etc. (define_insn_reservation "vec_fcmp" 3 - (eq_attr "type" "vfrecp,vfminmax,vfcmp,vfsgnj,vfclass,vfcvtitof,\ - vfcvtftoi,vfwcvtitof,vfwcvtftoi,vfwcvtftof,vfncvtitof,\ - vfncvtftoi,vfncvtftof,vfncvtbf16,vfwcvtbf16") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vfrecp,vfminmax,vfcmp,vfsgnj,vfclass,vfcvtitof,\ + vfcvtftoi,vfwcvtitof,vfwcvtftoi,vfwcvtftof,vfncvtitof,\ + vfncvtftoi,vfncvtftof,vfncvtbf16,vfwcvtbf16")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector integer multiplication. (define_insn_reservation "vec_imul" 4 - (eq_attr "type" "vimul,viwmul,vimuladd,viwmuladd,vsmul,vclmul,vclmulh,\ - vghsh,vgmul") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vimul,viwmul,vimuladd,viwmuladd,vsmul,vclmul,vclmulh,\ + vghsh,vgmul")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector float addition. (define_insn_reservation "vec_fadd" 4 - (eq_attr "type" "vfalu,vfwalu") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vfalu,vfwalu")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector float multiplication and FMA. (define_insn_reservation "vec_fmul" 6 - (eq_attr "type" "vfmul,vfwmul,vfmuladd,vfwmuladd,vfwmaccbf16,sf_vqmacc,sf_vfnrclip") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vfmul,vfwmul,vfmuladd,vfwmuladd,vfwmaccbf16,sf_vqmacc,sf_vfnrclip")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector crypto, assumed to be a generic operation for now. (define_insn_reservation "vec_crypto" 4 - (eq_attr "type" "crypto,vclz,vctz,vcpop") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "crypto,vclz,vctz,vcpop")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector crypto, AES (define_insn_reservation "vec_crypto_aes" 4 - (eq_attr "type" "vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector crypto, sha (define_insn_reservation "vec_crypto_sha" 4 - (eq_attr "type" "vsha2ms,vsha2ch,vsha2cl") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vsha2ms,vsha2ch,vsha2cl")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector crypto, SM3/4 (define_insn_reservation "vec_crypto_sm" 4 - (eq_attr "type" "vsm4k,vsm4r,vsm3me,vsm3c") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vsm4k,vsm4r,vsm3me,vsm3c")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector permute. (define_insn_reservation "vec_perm" 3 - (eq_attr "type" "vimerge,vfmerge,vslideup,vslidedown,vislide1up,\ - vislide1down,vfslide1up,vfslide1down,vgather,vcompress") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vimerge,vfmerge,vslideup,vslidedown,vislide1up,\ + vislide1down,vfslide1up,vfslide1down,vgather,vcompress")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector reduction. (define_insn_reservation "vec_reduction" 8 - (eq_attr "type" "vired,viwred,vfredu,vfwredu") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vired,viwred,vfredu,vfwredu")) "vxu_ooo_issue,vxu_ooo_multicycle") ;; Vector ordered reduction, assume the latency number is for ;; a 128-bit vector. It is scaled in riscv_sched_adjust_cost ;; for larger vectors. (define_insn_reservation "vec_ordered_reduction" 10 - (eq_attr "type" "vfredo,vfwredo") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vfredo,vfwredo")) "vxu_ooo_issue,vxu_ooo_multicycle*3") ;; Vector integer division, assume not pipelined. (define_insn_reservation "vec_idiv" 16 - (eq_attr "type" "vidiv") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vidiv")) "vxu_ooo_issue,vxu_ooo_multicycle*3") ;; Vector float divisions and sqrt, assume not pipelined. (define_insn_reservation "vec_float_divsqrt" 16 - (eq_attr "type" "vfdiv,vfsqrt") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vfdiv,vfsqrt")) "vxu_ooo_issue,vxu_ooo_multicycle*3") ;; Vector mask operations. (define_insn_reservation "vec_mask" 2 - (eq_attr "type" "vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,\ - vfmovvf,vfmovfv") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,\ + vfmovvf,vfmovfv")) "vxu_ooo_issue,vxu_ooo_alu") ;; Vector vsetvl. (define_insn_reservation "vec_vesetvl" 1 - (eq_attr "type" "vsetvl,vsetvl_pre") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "vsetvl,vsetvl_pre")) "vxu_ooo_issue") ;; Vector rounding mode setters, assume pipeline barrier. (define_insn_reservation "vec_setrm" 20 - (eq_attr "type" "wrvxrm,wrfrm") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "wrvxrm,wrfrm")) "vxu_ooo_issue,vxu_ooo_issue*3") ;; Vector read vlen/vlenb. (define_insn_reservation "vec_readlen" 4 - (eq_attr "type" "rdvlenb,rdvl") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "rdvlenb,rdvl")) "vxu_ooo_issue,vxu_ooo_issue") ;; Vector sf_vcp. (define_insn_reservation "vec_sf_vcp" 2 - (eq_attr "type" "sf_vc,sf_vc_se") + (and (eq_attr "tune" "generic_ooo,generic") + (eq_attr "type" "sf_vc,sf_vc_se")) "vxu_ooo_issue") diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index b75cec1..02554c5 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -601,8 +601,8 @@ constantpool_address_p (const_rtx addr) /* Make sure the address is word aligned. */ offset = XEXP (addr, 1); - if ((!CONST_INT_P (offset)) - || ((INTVAL (offset) & 3) != 0)) + if (! CONST_INT_P (offset) + || (INTVAL (offset) & 3) != 0) return false; sym = XEXP (addr, 0); @@ -611,6 +611,7 @@ constantpool_address_p (const_rtx addr) if (SYMBOL_REF_P (sym) && CONSTANT_POOL_ADDRESS_P (sym)) return true; + return false; } @@ -4694,29 +4695,32 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code, } } +/* Return TRUE if the specified insn corresponds to one or more L32R machine + instructions. */ + static bool xtensa_is_insn_L32R_p (const rtx_insn *insn) { - rtx x = PATTERN (insn); + rtx pat, dest, src; - if (GET_CODE (x) != SET) + /* "PATTERN (insn)" can be used without checking, see insn_cost() + in gcc/rtlanal.cc. */ + if (GET_CODE (pat = PATTERN (insn)) != SET + || ! register_operand (dest = SET_DEST (pat), VOIDmode)) return false; - x = XEXP (x, 1); - if (MEM_P (x)) - { - x = XEXP (x, 0); - return (SYMBOL_REF_P (x) || CONST_INT_P (x)) - && CONSTANT_POOL_ADDRESS_P (x); - } - - /* relaxed MOVI instructions, that will be converted to L32R by the - assembler. */ - if (CONST_INT_P (x) - && ! xtensa_simm12b (INTVAL (x))) + if (constantpool_mem_p (src = SET_SRC (pat))) return true; - return false; + /* Return true if: + - CONST16 instruction is not configured, and + - the source is some constant, and also + - negation of "the source is integer and fits into the immediate + field". */ + return (!TARGET_CONST16 + && CONSTANT_P (src) + && ! ((GET_MODE (dest) == SImode || GET_MODE (dest) == HImode) + && CONST_INT_P (src) && xtensa_simm12b (INTVAL (src)))); } /* Compute a relative costs of RTL insns. This is necessary in order to @@ -4725,7 +4729,7 @@ xtensa_is_insn_L32R_p (const rtx_insn *insn) static int xtensa_insn_cost (rtx_insn *insn, bool speed) { - if (!(recog_memoized (insn) < 0)) + if (! (recog_memoized (insn) < 0)) { int len = get_attr_length (insn); @@ -4738,7 +4742,7 @@ xtensa_insn_cost (rtx_insn *insn, bool speed) /* "L32R" may be particular slow (implementation-dependent). */ if (xtensa_is_insn_L32R_p (insn)) - return COSTS_N_INSNS (1 + xtensa_extra_l32r_costs); + return COSTS_N_INSNS ((1 + xtensa_extra_l32r_costs) * n); /* Cost based on the pipeline model. */ switch (get_attr_type (insn)) @@ -4783,7 +4787,7 @@ xtensa_insn_cost (rtx_insn *insn, bool speed) { /* "L32R" itself plus constant in litpool. */ if (xtensa_is_insn_L32R_p (insn)) - len = 3 + 4; + len += (len / 3) * 4; /* Consider fractional instruction length (for example, ".n" short instructions or "L32R" litpool constants. */ diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 029be99..629dfdd 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1297,7 +1297,10 @@ std::swap (operands[0], operands[1]); std::swap (operands[2], operands[3]); } -}) +} + [(set_attr "type" "move,move,load,load,store") + (set_attr "mode" "DI") + (set_attr "length" "6,12,6,6,6")]) (define_split [(set (match_operand:DI 0 "register_operand") @@ -1344,7 +1347,7 @@ %v0s32i\t%1, %0 rsr\t%0, ACCLO wsr\t%1, ACCLO" - [(set_attr "type" "move,move,move,load,store,store,move,move,move,move,move,load,load,store,rsr,wsr") + [(set_attr "type" "move,move,move,load,store,store,move,move,move,load,move,load,load,store,rsr,wsr") (set_attr "mode" "SI") (set_attr "length" "2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3")]) @@ -1410,7 +1413,7 @@ %v0s16i\t%1, %0 rsr\t%0, ACCLO wsr\t%1, ACCLO" - [(set_attr "type" "move,move,move,move,move,load,load,store,rsr,wsr") + [(set_attr "type" "move,move,move,move,load,load,load,store,rsr,wsr") (set_attr "mode" "HI") (set_attr "length" "2,2,3,3,3,3,3,3,3,3")]) @@ -1519,7 +1522,7 @@ const16\t%0, %t1\;const16\t%0, %b1 %v1l32i\t%0, %1 %v0s32i\t%1, %0" - [(set_attr "type" "farith,fload,fstore,move,load,load,store,move,farith,farith,move,move,load,store") + [(set_attr "type" "farith,fload,fstore,move,load,load,store,move,farith,farith,load,move,load,store") (set_attr "mode" "SF") (set_attr "length" "3,3,3,2,3,2,2,3,3,3,3,6,3,3")]) @@ -1643,7 +1646,10 @@ std::swap (operands[0], operands[1]); std::swap (operands[2], operands[3]); } -}) +} + [(set_attr "type" "move,load,move,load,load,store") + (set_attr "mode" "DF") + (set_attr "length" "6,6,12,6,6,6")]) ;; Block moves diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a2c1271..76d21f1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2025-07-22 Jason Merrill <jason@redhat.com> + + PR c++/121068 + * constexpr.cc (cxx_eval_store_expression): Allow ARRAY_REFs + when activating an array member of a union. + 2025-07-21 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> * semantics.cc (finish_asm_stmt): Pass null pointer to diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index ee06858..1a77954 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -7736,13 +7736,24 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (*valp), first, NULL_TREE); /* Check for implicit change of active member for a union. */ + + /* LWG3436, CWG2675, c++/121068: The array object model is confused. For + now allow initializing an array element to activate the array. */ + auto only_array_refs = [](const releasing_vec &refs) + { + for (unsigned i = 1; i < refs->length(); i += 3) + if (TREE_CODE ((*refs)[i]) != INTEGER_CST) + return false; + return true; + }; + if (code == UNION_TYPE && (CONSTRUCTOR_NELTS (*valp) == 0 || CONSTRUCTOR_ELT (*valp, 0)->index != index) /* An INIT_EXPR of the last member in an access chain is always OK, but still check implicit change of members earlier on; see cpp2a/constexpr-union6.C. */ - && !(TREE_CODE (t) == INIT_EXPR && refs->is_empty ())) + && !(TREE_CODE (t) == INIT_EXPR && only_array_refs (refs))) { bool has_active_member = CONSTRUCTOR_NELTS (*valp) != 0; tree inner = strip_array_types (reftype); diff --git a/gcc/genpreds.cc b/gcc/genpreds.cc index c6a2983..4f8beeb 100644 --- a/gcc/genpreds.cc +++ b/gcc/genpreds.cc @@ -1184,7 +1184,12 @@ write_insn_constraint_len (void) puts (" default: break;\n" " }\n" " if (str[0] == '{')\n" - " return ((const char *) rawmemchr (str + 1, '}') - str) + 1;\n" + " {\n" + " size_t len = 1;\n" + " while (str[len] != '}' && str[len] != '\\0')\n" + " ++len;\n" + " return len + 1;\n" + " }\n" " return 1;\n" "}\n"); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d74b461..0a07d46 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,38 @@ +2025-07-22 Jason Merrill <jason@redhat.com> + + PR c++/121068 + * g++.dg/cpp2a/constexpr-union6.C: Expect x5 to work. + * g++.dg/cpp26/constexpr-new4.C: New test. + +2025-07-22 Jason Merrill <jason@redhat.com> + + * g++.dg/warn/Wmismatched-new-delete-5.C: Fix allocation. + +2025-07-22 Andrew Pinski <quic_apinski@quicinc.com> + + PR middle-end/109267 + * lib/target-supports.exp (check_effective_target_trap): New proc. + * g++.dg/missing-return.C: Update testcase for the !trap case. + * gcc.dg/pr109267-1.c: New test. + * gcc.dg/pr109267-2.c: New test. + +2025-07-22 Karl Meakin <karl.meakin@arm.com> + + * gcc.target/aarch64/sve/mask_load_2.c: Update tests. + +2025-07-22 Karl Meakin <karl.meakin@arm.com> + + * gcc.target/aarch64/sve/mask_load_2.c: New test. + +2025-07-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/121202 + * gcc.dg/pr121202.c: New testcase. + +2025-07-22 Richard Biener <rguenther@suse.de> + + * gcc.dg/vect/slp-28.c: Adjust. + 2025-07-21 Andrew Pinski <quic_apinski@quicinc.com> PR tree-optimization/110949 diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-new4.C b/gcc/testsuite/g++.dg/cpp26/constexpr-new4.C new file mode 100644 index 0000000..12d8a46 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-new4.C @@ -0,0 +1,21 @@ +// PR c++/121068 +// { dg-do compile { target c++26 } } + +constexpr void *operator new (__SIZE_TYPE__, void *p) { return p; } +constexpr void *operator new[] (__SIZE_TYPE__, void *p) { return p; } + +consteval int +foo() +{ + using T = int; + union { T arr[3]; }; + new(arr) T[3]; // makes arr active + for (int i = 0; i < 3; ++i) + arr[i].~T(); + + new (arr + 2) T{10}; // A + + return 1; +}; + +constexpr int g = foo(); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C index 00bda53..ab8c979 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C @@ -45,9 +45,9 @@ constexpr int test5() { union { int data[1]; } u; - std::construct_at(u.data, 0); // { dg-message "in .constexpr. expansion" } + std::construct_at(u.data, 0); // { dg-bogus "in .constexpr. expansion" } return 0; } -constexpr int x5 = test5(); // { dg-message "in .constexpr. expansion" } +constexpr int x5 = test5(); // { dg-bogus "in .constexpr. expansion" } // { dg-error "accessing (uninitialized member|.* member instead of)" "" { target *-*-* } 0 } diff --git a/gcc/testsuite/g++.dg/missing-return.C b/gcc/testsuite/g++.dg/missing-return.C index 5f8e2cc..f6934b0 100644 --- a/gcc/testsuite/g++.dg/missing-return.C +++ b/gcc/testsuite/g++.dg/missing-return.C @@ -5,4 +5,6 @@ int foo(int a) { } /* { dg-warning "no return statement" } */ -/* { dg-final { scan-tree-dump "__builtin_unreachable" "optimized" } } */ +/* For targets without traps, it will be an infinite loop */ +/* { dg-final { scan-tree-dump "__builtin_unreachable" "optimized" { target trap } } } */ +/* { dg-final { scan-tree-dump "goto <" "optimized" { target { ! trap } } } } */ diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C index bac2b68..a21e864 100644 --- a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C +++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C @@ -31,7 +31,7 @@ void warn_placement_new () void warn_placement_array_new () { - void *p = malloc (sizeof (int)); + void *p = malloc (sizeof (int) * 2); int *q = new (p) int[2]; delete q; // { dg-warning "-Wmismatched-new-delete" } } diff --git a/gcc/testsuite/gcc.dg/pr109267-1.c b/gcc/testsuite/gcc.dg/pr109267-1.c new file mode 100644 index 0000000..e762e59 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109267-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +/* PR middle-end/109267 */ + +int f(void) +{ + __builtin_unreachable(); +} + +/* This unreachable should be changed to be a trap. */ + +/* { dg-final { scan-tree-dump-times "__builtin_unreachable trap \\\(" 1 "optimized" { target trap } } } */ +/* { dg-final { scan-tree-dump-times "goto <" 1 "optimized" { target { ! trap } } } } */ +/* { dg-final { scan-tree-dump-not "__builtin_unreachable \\\(" "optimized"} } */ diff --git a/gcc/testsuite/gcc.dg/pr109267-2.c b/gcc/testsuite/gcc.dg/pr109267-2.c new file mode 100644 index 0000000..6cd1419 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109267-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +/* PR middle-end/109267 */ +void g(void); +int f(int *t) +{ + g(); + __builtin_unreachable(); +} + +/* The unreachable should stay a unreachable. */ +/* { dg-final { scan-tree-dump-not "__builtin_unreachable trap \\\(" "optimized"} } */ +/* { dg-final { scan-tree-dump-times "__builtin_unreachable \\\(" 1 "optimized"} } */ diff --git a/gcc/testsuite/gcc.dg/pr121202.c b/gcc/testsuite/gcc.dg/pr121202.c new file mode 100644 index 0000000..30ecf4a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr121202.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fno-tree-copy-prop" } */ + +int a, b, c; +int e(int f, int g) { return f >> g; } +int h(int f) { return a > 1 ? 0 : f << a; } +int main() { + while (c--) + b = e(h(1), a); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c index 9ba43be..ef35b29 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c @@ -4,6 +4,7 @@ int a, b, c, d[6], e = 3, f; void abort (void); +void fn1 () __attribute__((noinline)); void fn1 () { for (b = 1; b < 5; b++) diff --git a/gcc/testsuite/gcc.dg/vect/pr116125.c b/gcc/testsuite/gcc.dg/vect/pr116125.c index eab9efd..1b882ec 100644 --- a/gcc/testsuite/gcc.dg/vect/pr116125.c +++ b/gcc/testsuite/gcc.dg/vect/pr116125.c @@ -17,12 +17,12 @@ main (void) { check_vect (); - struct st a[9] = {}; + struct st a[10] = {}; - // input a = 0, 0, 0, 0, 0, 0, 0, 0, 0 + // input a = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 mem_overlap (&a[1], a); - // output a = 0, 1, 2, 3, 4, 5, 6, 7, 8 + // output a = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 if (a[2].num == 2) return 0; else diff --git a/gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c b/gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c new file mode 100644 index 0000000..66d9510 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c @@ -0,0 +1,23 @@ +// { dg-do compile } +// { dg-options "-march=armv8-a+sve -msve-vector-bits=128 -O3" } + +typedef struct Array { + int elems[3]; +} Array; + +int loop(Array **pp, int len, int idx) { + int nRet = 0; + + #pragma GCC unroll 0 + for (int i = 0; i < len; i++) { + Array *p = pp[i]; + if (p) { + nRet += p->elems[idx]; + } + } + + return nRet; +} + +// { dg-final { scan-assembler-times {ld1w\tz[0-9]+\.d, p[0-7]/z} 1 } } +// { dg-final { scan-assembler-times {add\tz[0-9]+\.s, p[0-7]/m} 1 } } diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 65d2e67..30d12a9 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -1017,6 +1017,18 @@ proc check_effective_target_label_values {} { return 1 } + +# Return 1 if builtin_trap expands not into a call but an instruction, +# 0 otherwise. +proc check_effective_target_trap { } { + return [check_no_messages_and_pattern trap "!\\(call" rtl-expand { + void foo () + { + return __builtin_trap (); + } + } "" ] +} + # Return 1 if builtin_return_address and builtin_frame_address are # supported, 0 otherwise. diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc index a34a51e..5aaa18d 100644 --- a/gcc/tree-cfgcleanup.cc +++ b/gcc/tree-cfgcleanup.cc @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-into-ssa.h" #include "tree-cfgcleanup.h" #include "gimple-pretty-print.h" +#include "target.h" /* The set of blocks in that at least one of the following changes happened: @@ -1569,6 +1570,29 @@ execute_cleanup_cfg_post_optimizing (void) cleanup_dead_labels (); if (group_case_labels ()) todo |= TODO_cleanup_cfg; + + basic_block bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb); + /* If the first (and only) bb and the only non debug + statement is __builtin_unreachable call, then replace it with a trap + so the function is at least one instruction in size. */ + if (!gsi_end_p (gsi) + && gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_UNREACHABLE)) + { + if (targetm.have_trap ()) + { + gimple_call_set_fndecl (gsi_stmt (gsi), builtin_decl_implicit (BUILT_IN_UNREACHABLE_TRAP)); + update_stmt (gsi_stmt (gsi)); + } + /* If the target does not have a trap, convert it into an infinite loop. */ + else + { + gsi_remove (&gsi, true); + make_single_succ_edge (bb, bb, EDGE_FALLTHRU); + fix_loop_structure (NULL); + } + } + if ((flag_compare_debug_opt || flag_compare_debug) && flag_dump_final_insns) { diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc index a24ddfb..460a48d 100644 --- a/gcc/tree-vect-data-refs.cc +++ b/gcc/tree-vect-data-refs.cc @@ -4667,26 +4667,19 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, if (off == NULL_TREE) off = size_zero_node; - /* If base is not loop invariant, either off is 0, then we start with just - the constant offset in the loop invariant BASE and continue with base - as OFF, otherwise give up. - We could handle that case by gimplifying the addition of base + off - into some SSA_NAME and use that as off, but for now punt. */ + /* BASE must be loop invariant. If it is not invariant, but OFF is, then we + * can fix that by swapping BASE and OFF. */ if (!expr_invariant_in_loop_p (loop, base)) { - if (!integer_zerop (off)) + if (!expr_invariant_in_loop_p (loop, off)) return false; - off = base; - base = size_int (pbytepos); - } - /* Otherwise put base + constant offset into the loop invariant BASE - and continue with OFF. */ - else - { - base = fold_convert (sizetype, base); - base = size_binop (PLUS_EXPR, base, size_int (pbytepos)); + + std::swap (base, off); } + base = fold_convert (sizetype, base); + base = size_binop (PLUS_EXPR, base, size_int (pbytepos)); + /* OFF at this point may be either a SSA_NAME or some tree expression from get_inner_reference. Try to peel off loop invariants from it into BASE as long as possible. */ @@ -4864,6 +4857,9 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, offset_vectype = NULL_TREE; } + gcc_checking_assert (expr_invariant_in_loop_p (loop, base)); + gcc_checking_assert (!expr_invariant_in_loop_p (loop, off)); + info->ifn = ifn; info->decl = decl; info->base = base; diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 7ad56b9..7776b2f 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -11370,7 +11370,11 @@ vect_schedule_slp_node (vec_info *vinfo, && !SSA_NAME_IS_DEFAULT_DEF (def)) { gimple *stmt = SSA_NAME_DEF_STMT (def); - if (!last_stmt) + if (gimple_uid (stmt) == -1u) + /* If the stmt is not inside the region do not + use it as possible insertion point. */ + ; + else if (!last_stmt) last_stmt = stmt; else if (vect_stmt_dominates_stmt_p (last_stmt, stmt)) last_stmt = stmt; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index cf86ee2..68efd05 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,33 @@ +2025-07-22 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/119137 + * testsuite/23_containers/inplace_vector/cons/from_range.cc: Run + iterators and range test at compile-time. + * testsuite/23_containers/inplace_vector/modifiers/assign.cc: + Likewise. + * testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc: + Likewise. + * testsuite/util/testsuite_iterators.h (__gnu_test::BoundsContainer) + (__gnu_test::OutputContainer, __gnu_test::WritableObject) + (__gnu_test::output_iterator_wrapper, __gnu_test::input_iterator_wrapper) + (__gnu_test::forward_iterator_wrapper) + (__gnu_test::bidirectional_iterator_wrapper) + (__gnu_test::random_access_iterator_wrapper) + (__gnu_test::test_container): Add appropriate _GLIBCXXNN_CONSTEXPR + macros to member functions. + (__gnu_test::contiguous_iterator_wrapper) + (__gnu_test::input_iterator_wrapper_rval) + (__gnu_test::test_range, __gnu_test::test_range_nocopy) + (__gnu_test::test_sized_range_sized_sent) + (__gnu_test::test_sized_range): Add constexpr specifier to member + functions. + +2025-07-22 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/119137 + * include/std/inplace_vector (inplace_vector::assign_range): + Replace _Nm with _M_size in the assigment loop. + 2025-07-21 Luc Grosheintz <luc.grosheintz@gmail.com> * include/std/mdspan (mdspan::mdspan): Make default ctor diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc index 5fa8a5d..4a2f193 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc @@ -70,7 +70,7 @@ do_test_it() #endif } -bool +constexpr bool test_iterators() { using namespace __gnu_test; @@ -131,7 +131,7 @@ do_test_r() #endif } -bool +constexpr bool test_ranges() { using namespace __gnu_test; @@ -152,9 +152,9 @@ test_ranges() // Not lvalue-convertible to int struct C { - C(int v) : val(v) { } - operator int() && { return val; } - bool operator==(int b) const { return b == val; } + constexpr C(int v) : val(v) { } + constexpr operator int() && { return val; } + constexpr bool operator==(int b) const { return b == val; } int val; }; using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; @@ -163,22 +163,15 @@ test_ranges() return true; } -constexpr bool -test_constexpr() -{ - // XXX: this doesn't test the non-forward_range code paths are constexpr. - std::initializer_list<int> il{1, 2, 3, 4}; - std::inplace_vector<int, 6> v(il.begin(), il.end()); - eq<int>(v, il); - - do_test_r<std::span<short>>(); - return true; -} - int main() { - test_iterators(); - test_ranges(); - static_assert( test_constexpr() ); + auto test_all = [] { + test_iterators(); + test_ranges(); + return true; + }; + + test_all(); + static_assert( test_all() ); } diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc index 91132be..65b505e 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc @@ -204,14 +204,10 @@ template<size_t N, typename T> constexpr void test_assign_empty() { - // TODO make test iterators consteval - if !consteval - { - using namespace __gnu_test; - test_assign_empty_it<N, T, input_iterator_wrapper>(); - test_assign_empty_it<N, T, forward_iterator_wrapper>(); - test_assign_empty_it<N, T, random_access_iterator_wrapper>(); - } + using namespace __gnu_test; + test_assign_empty_it<N, T, input_iterator_wrapper>(); + test_assign_empty_it<N, T, forward_iterator_wrapper>(); + test_assign_empty_it<N, T, random_access_iterator_wrapper>(); test_assign_empty_other<N, T>; } @@ -339,23 +335,20 @@ constexpr void test_assigns() { using namespace __gnu_test; - // TODO make test iterators consteval - if !consteval { - test_assign_range<test_forward_range<int>>(); - test_assign_range<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); - - test_assign_range<test_input_range<int>>(); - test_assign_range<test_input_sized_range<int>>(); - test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); - - test_assign_range<test_range<int, input_iterator_wrapper_nocopy>>(); - test_assign_range<test_sized_range<int, input_iterator_wrapper_nocopy>>(); - test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); - - test_assign_iterators<T, input_iterator_wrapper>(); - test_assign_iterators<T, forward_iterator_wrapper>(); - test_assign_iterators<T, random_access_iterator_wrapper>(); - } + test_assign_range<test_forward_range<int>>(); + test_assign_range<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); + + test_assign_range<test_input_range<int>>(); + test_assign_range<test_input_sized_range<int>>(); + test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); + + test_assign_range<test_range<int, input_iterator_wrapper_nocopy>>(); + test_assign_range<test_sized_range<int, input_iterator_wrapper_nocopy>>(); + test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); + + test_assign_iterators<T, input_iterator_wrapper>(); + test_assign_iterators<T, forward_iterator_wrapper>(); + test_assign_iterators<T, random_access_iterator_wrapper>(); test_assign_initializer_list<T>(); test_assign_repeated<T>(); diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc index 072f0b3..6a5b62f 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc @@ -227,12 +227,10 @@ constexpr void test_add_to_full() { using namespace __gnu_test; - // TODO make test iterators consteval - if !consteval { - test_add_to_full_it<N, T, input_iterator_wrapper>(); - test_add_to_full_it<N, T, forward_iterator_wrapper>(); - test_add_to_full_it<N, T, random_access_iterator_wrapper>(); - } + test_add_to_full_it<N, T, input_iterator_wrapper>(); + test_add_to_full_it<N, T, forward_iterator_wrapper>(); + test_add_to_full_it<N, T, random_access_iterator_wrapper>(); + test_add_to_full_other<N, T>(); } @@ -566,34 +564,31 @@ constexpr void test_inserts() { using namespace __gnu_test; - // TODO make test iterators consteval - if !consteval { - do_test_ranges<test_forward_range<int>>(); - do_test_ranges<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); + do_test_ranges<test_forward_range<int>>(); + do_test_ranges<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); - do_test_ranges<test_input_range<int>>(); - do_test_ranges<test_input_sized_range<int>>(); - do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); + do_test_ranges<test_input_range<int>>(); + do_test_ranges<test_input_sized_range<int>>(); + do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); - do_test_ranges<test_range<int, input_iterator_wrapper_nocopy>>(); - do_test_ranges<test_sized_range<int, input_iterator_wrapper_nocopy>>(); - do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); + do_test_ranges<test_range<int, input_iterator_wrapper_nocopy>>(); + do_test_ranges<test_sized_range<int, input_iterator_wrapper_nocopy>>(); + do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); - test_insert_iterators<T, input_iterator_wrapper>(); - test_insert_iterators<T, forward_iterator_wrapper>(); - test_insert_iterators<T, random_access_iterator_wrapper>(); - } + test_insert_iterators<T, input_iterator_wrapper>(); + test_insert_iterators<T, forward_iterator_wrapper>(); + test_insert_iterators<T, random_access_iterator_wrapper>(); - test_insert_initializer_list<T>(); - test_insert_repeated<T>(); +test_insert_initializer_list<T>(); +test_insert_repeated<T>(); } int main() { - auto test_all = []{ - test_add_to_full<0, int>(); - test_add_to_full<0, X>(); - test_add_to_full<4, int>(); +auto test_all = []{ + test_add_to_full<0, int>(); + test_add_to_full<0, X>(); + test_add_to_full<4, int>(); test_inserts<int>(); #ifdef __cpp_lib_constexpr_inplace_vector diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h index e9f8f56..acd412a 100644 --- a/libstdc++-v3/testsuite/util/testsuite_iterators.h +++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h @@ -61,10 +61,12 @@ namespace __gnu_test T* first; T* last; + _GLIBCXX_CONSTEXPR BoundsContainer(T* _first, T* _last) : first(_first), last(_last) { } - std::size_t size() const { return last - first; } + _GLIBCXX_CONSTEXPR std::size_t + size() const { return last - first; } }; // Simple container for holding state of a set of output iterators. @@ -74,11 +76,13 @@ namespace __gnu_test T* incrementedto; bool* writtento; + _GLIBCXX20_CONSTEXPR OutputContainer(T* _first, T* _last) : BoundsContainer<T>(_first, _last), incrementedto(_first), writtento(new bool[this->size()]()) { } + _GLIBCXX20_CONSTEXPR ~OutputContainer() { delete[] writtento; } }; @@ -92,12 +96,14 @@ namespace __gnu_test public: OutputContainer<T>* SharedInfo; + _GLIBCXX_CONSTEXPR WritableObject(T* ptr_in, OutputContainer<T>* SharedInfo_in): ptr(ptr_in), SharedInfo(SharedInfo_in) { } #if __cplusplus >= 201103L template<class U> + _GLIBCXX14_CONSTEXPR typename std::enable_if<std::is_assignable<T&, U>::value>::type operator=(U&& new_val) const { @@ -107,6 +113,7 @@ namespace __gnu_test } #else template<class U> + _GLIBCXX14_CONSTEXPR void operator=(const U& new_val) { @@ -128,6 +135,7 @@ namespace __gnu_test struct output_iterator_wrapper { protected: + _GLIBCXX_CONSTEXPR output_iterator_wrapper() : ptr(0), SharedInfo(0) { } @@ -142,6 +150,7 @@ namespace __gnu_test T* ptr; ContainerType* SharedInfo; + _GLIBCXX14_CONSTEXPR output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) : ptr(_ptr), SharedInfo(SharedInfo_in) { @@ -155,6 +164,7 @@ namespace __gnu_test operator=(const output_iterator_wrapper&) = default; #endif + _GLIBCXX14_CONSTEXPR WritableObject<T> operator*() const { @@ -163,6 +173,7 @@ namespace __gnu_test return WritableObject<T>(ptr, SharedInfo); } + _GLIBCXX14_CONSTEXPR output_iterator_wrapper& operator++() { @@ -173,6 +184,7 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR output_iterator_wrapper operator++(int) { @@ -224,13 +236,19 @@ namespace __gnu_test struct deref_proxy { T* ptr; - operator const T&() const { return *ptr; } + + _GLIBCXX_CONSTEXPR + operator const T&() const + { return *ptr; } } p; - deref_proxy operator*() const { return p; } + _GLIBCXX_CONSTEXPR + deref_proxy operator*() const + { return p; } }; protected: + _GLIBCXX_CONSTEXPR input_iterator_wrapper() : ptr(0), SharedInfo(0) { } @@ -245,6 +263,7 @@ namespace __gnu_test T* ptr; ContainerType* SharedInfo; + _GLIBCXX14_CONSTEXPR input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) : ptr(_ptr), SharedInfo(SharedInfo_in) { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); } @@ -256,6 +275,7 @@ namespace __gnu_test operator=(const input_iterator_wrapper&) = default; #endif + _GLIBCXX14_CONSTEXPR bool operator==(const input_iterator_wrapper& in) const { @@ -264,32 +284,34 @@ namespace __gnu_test return ptr == in.ptr; } + _GLIBCXX14_CONSTEXPR bool operator!=(const input_iterator_wrapper& in) const { return !(*this == in); } - T* - base() const + _GLIBCXX_CONSTEXPR + T* base() const { return ptr; } - T& - operator*() const + _GLIBCXX14_CONSTEXPR + T& operator*() const { ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); ITERATOR_VERIFY(ptr >= SharedInfo->first); return *ptr; } - T* - operator->() const + _GLIBCXX14_CONSTEXPR + T* operator->() const { return &**this; } + _GLIBCXX14_CONSTEXPR input_iterator_wrapper& operator++() { @@ -300,6 +322,7 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR post_inc_proxy operator++(int) { @@ -340,10 +363,12 @@ namespace __gnu_test typedef BoundsContainer<T> ContainerType; typedef std::forward_iterator_tag iterator_category; + _GLIBCXX14_CONSTEXPR forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) : input_iterator_wrapper<T>(_ptr, SharedInfo_in) { } + _GLIBCXX14_CONSTEXPR forward_iterator_wrapper() { } @@ -354,17 +379,18 @@ namespace __gnu_test operator=(const forward_iterator_wrapper&) = default; #endif - T& - operator*() const + _GLIBCXX14_CONSTEXPR + T& operator*() const { ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); return *(this->ptr); } - T* - operator->() const + _GLIBCXX14_CONSTEXPR + T* operator->() const { return &**this; } + _GLIBCXX14_CONSTEXPR forward_iterator_wrapper& operator++() { @@ -373,6 +399,7 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR forward_iterator_wrapper operator++(int) { @@ -382,8 +409,8 @@ namespace __gnu_test } #if __cplusplus >= 201402L - bool - operator==(const forward_iterator_wrapper& it) const noexcept + constexpr + bool operator==(const forward_iterator_wrapper& it) const noexcept { // Since C++14 value-initialized forward iterators are comparable. if (this->SharedInfo == nullptr || it.SharedInfo == nullptr) @@ -394,8 +421,8 @@ namespace __gnu_test return base_this == base_that; } - bool - operator!=(const forward_iterator_wrapper& it) const noexcept + constexpr + bool operator!=(const forward_iterator_wrapper& it) const noexcept { return !(*this == it); } @@ -415,10 +442,12 @@ namespace __gnu_test typedef BoundsContainer<T> ContainerType; typedef std::bidirectional_iterator_tag iterator_category; + _GLIBCXX14_CONSTEXPR bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) : forward_iterator_wrapper<T>(_ptr, SharedInfo_in) { } + _GLIBCXX14_CONSTEXPR bidirectional_iterator_wrapper() : forward_iterator_wrapper<T>() { } @@ -431,6 +460,7 @@ namespace __gnu_test operator=(const bidirectional_iterator_wrapper&) = default; #endif + _GLIBCXX14_CONSTEXPR bidirectional_iterator_wrapper& operator++() { @@ -439,6 +469,7 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR bidirectional_iterator_wrapper operator++(int) { @@ -447,6 +478,7 @@ namespace __gnu_test return tmp; } + _GLIBCXX14_CONSTEXPR bidirectional_iterator_wrapper& operator--() { @@ -455,6 +487,7 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR bidirectional_iterator_wrapper operator--(int) { @@ -478,10 +511,12 @@ namespace __gnu_test typedef BoundsContainer<T> ContainerType; typedef std::random_access_iterator_tag iterator_category; + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in) { } + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper() : bidirectional_iterator_wrapper<T>() { } @@ -494,6 +529,7 @@ namespace __gnu_test operator=(const random_access_iterator_wrapper&) = default; #endif + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper& operator++() { @@ -502,6 +538,7 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper operator++(int) { @@ -510,6 +547,7 @@ namespace __gnu_test return tmp; } + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper& operator--() { @@ -518,6 +556,7 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper operator--(int) { @@ -526,6 +565,7 @@ namespace __gnu_test return tmp; } + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper& operator+=(std::ptrdiff_t n) { @@ -542,10 +582,12 @@ namespace __gnu_test return *this; } + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper& operator-=(std::ptrdiff_t n) { return *this += -n; } + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper operator-(std::ptrdiff_t n) const { @@ -553,6 +595,7 @@ namespace __gnu_test return tmp -= n; } + _GLIBCXX14_CONSTEXPR std::ptrdiff_t operator-(const random_access_iterator_wrapper<T>& in) const { @@ -560,42 +603,44 @@ namespace __gnu_test return this->ptr - in.ptr; } - T& - operator[](std::ptrdiff_t n) const + _GLIBCXX14_CONSTEXPR + T& operator[](std::ptrdiff_t n) const { return *(*this + n); } - bool - operator<(const random_access_iterator_wrapper<T>& in) const + _GLIBCXX14_CONSTEXPR + bool operator<(const random_access_iterator_wrapper<T>& in) const { ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); return this->ptr < in.ptr; } - bool - operator>(const random_access_iterator_wrapper<T>& in) const + _GLIBCXX14_CONSTEXPR + bool operator>(const random_access_iterator_wrapper<T>& in) const { return in < *this; } - bool - operator>=(const random_access_iterator_wrapper<T>& in) const + _GLIBCXX14_CONSTEXPR + bool operator>=(const random_access_iterator_wrapper<T>& in) const { return !(*this < in); } - bool - operator<=(const random_access_iterator_wrapper<T>& in) const + _GLIBCXX14_CONSTEXPR + bool operator<=(const random_access_iterator_wrapper<T>& in) const { return !(*this > in); } }; template<typename T> + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper<T> operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n) { return it += n; } template<typename T> + _GLIBCXX14_CONSTEXPR random_access_iterator_wrapper<T> operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it) { return it += n; } @@ -613,14 +658,17 @@ namespace __gnu_test { typename ItType<T>::ContainerType bounds; + _GLIBCXX_CONSTEXPR test_container(T* _first, T* _last) : bounds(_first, _last) { } template<std::size_t N> explicit + _GLIBCXX_CONSTEXPR test_container(T (&arr)[N]) : bounds(arr, arr+N) { } + _GLIBCXX14_CONSTEXPR ItType<T> it(int pos) { @@ -628,6 +676,7 @@ namespace __gnu_test return ItType<T>(bounds.first + pos, &bounds); } + _GLIBCXX14_CONSTEXPR ItType<T> it(T* pos) { @@ -635,18 +684,22 @@ namespace __gnu_test return ItType<T>(pos, &bounds); } + _GLIBCXX_CONSTEXPR const T& val(int pos) { return (bounds.first)[pos]; } + _GLIBCXX14_CONSTEXPR ItType<T> begin() { return it(bounds.first); } + _GLIBCXX14_CONSTEXPR ItType<T> end() { return it(bounds.last); } + _GLIBCXX_CONSTEXPR std::size_t size() const { return bounds.size(); } @@ -686,6 +739,7 @@ namespace __gnu_test // Use an integer-class type to try and break the library code. using difference_type = std::ranges::__detail::__max_diff_type; + constexpr contiguous_iterator_wrapper& operator++() { @@ -693,6 +747,7 @@ namespace __gnu_test return *this; } + constexpr contiguous_iterator_wrapper& operator--() { @@ -700,6 +755,7 @@ namespace __gnu_test return *this; } + constexpr contiguous_iterator_wrapper operator++(int) { @@ -708,6 +764,7 @@ namespace __gnu_test return tmp; } + constexpr contiguous_iterator_wrapper operator--(int) { @@ -716,6 +773,7 @@ namespace __gnu_test return tmp; } + constexpr contiguous_iterator_wrapper& operator+=(difference_type n) { @@ -724,23 +782,28 @@ namespace __gnu_test return *this; } - friend contiguous_iterator_wrapper + friend constexpr + contiguous_iterator_wrapper operator+(contiguous_iterator_wrapper iter, difference_type n) { return iter += n; } - friend contiguous_iterator_wrapper + friend constexpr + contiguous_iterator_wrapper operator+(difference_type n, contiguous_iterator_wrapper iter) { return iter += n; } + constexpr contiguous_iterator_wrapper& operator-=(difference_type n) { return *this += -n; } - friend contiguous_iterator_wrapper + friend constexpr + contiguous_iterator_wrapper operator-(contiguous_iterator_wrapper iter, difference_type n) { return iter -= n; } - friend difference_type + friend constexpr + difference_type operator-(contiguous_iterator_wrapper l, contiguous_iterator_wrapper r) { const random_access_iterator_wrapper<T>& lbase = l; @@ -748,6 +811,7 @@ namespace __gnu_test return static_cast<difference_type>(lbase - rbase); } + constexpr decltype(auto) operator[](difference_type n) const { auto d = static_cast<std::ptrdiff_t>(n); @@ -765,6 +829,7 @@ namespace __gnu_test { using input_iterator_wrapper<T>::input_iterator_wrapper; + constexpr input_iterator_wrapper_nocopy() : input_iterator_wrapper<T>(nullptr, nullptr) { } @@ -779,6 +844,7 @@ namespace __gnu_test using input_iterator_wrapper<T>::operator++; + constexpr input_iterator_wrapper_nocopy& operator++() { @@ -795,6 +861,7 @@ namespace __gnu_test using input_iterator_wrapper<T>::operator++; + constexpr input_iterator_wrapper_rval& operator++() { @@ -802,8 +869,8 @@ namespace __gnu_test return *this; } - T&& - operator*() const + constexpr + T&& operator*() const { return std::move(input_iterator_wrapper<T>::operator*()); } }; @@ -821,7 +888,9 @@ namespace __gnu_test using Iter<T>::operator++; - iterator& operator++() { Iter<T>::operator++(); return *this; } + constexpr + iterator& operator++() + { Iter<T>::operator++(); return *this; } }; template<typename I> @@ -829,21 +898,24 @@ namespace __gnu_test { T* end; - friend bool operator==(const sentinel& s, const I& i) noexcept + friend constexpr bool + operator==(const sentinel& s, const I& i) noexcept { return s.end == i.ptr; } - friend auto operator-(const sentinel& s, const I& i) noexcept + friend constexpr + auto operator-(const sentinel& s, const I& i) noexcept requires std::random_access_iterator<I> { return std::iter_difference_t<I>(s.end - i.ptr); } - friend auto operator-(const I& i, const sentinel& s) noexcept + friend constexpr auto + operator-(const I& i, const sentinel& s) noexcept requires std::random_access_iterator<I> { return std::iter_difference_t<I>(i.ptr - s.end); } }; protected: - auto - get_iterator(T* p) + constexpr + auto get_iterator(T* p) { if constexpr (std::default_initializable<Iter<T>>) return Iter<T>(p, &bounds); @@ -852,17 +924,19 @@ namespace __gnu_test } public: + constexpr test_range(T* first, T* last) : bounds(first, last) { } template<std::size_t N> - explicit + explicit constexpr test_range(T (&arr)[N]) : test_range(arr, arr+N) { } - auto begin() & { return get_iterator(bounds.first); } + constexpr auto begin() & + { return get_iterator(bounds.first); } - auto end() & + constexpr auto end() & { using I = decltype(get_iterator(bounds.last)); return sentinel<I>{bounds.last}; @@ -875,7 +949,9 @@ namespace __gnu_test template<typename T, template<typename> class Iter> struct test_range_nocopy : test_range<T, Iter> { - test_range_nocopy(T* first, T* last) : test_range<T, Iter>(first, last) + constexpr + test_range_nocopy(T* first, T* last) + : test_range<T, Iter>(first, last) {} test_range_nocopy(test_range_nocopy&&) = default; @@ -910,6 +986,7 @@ namespace __gnu_test { using test_range<T, Iter>::test_range; + constexpr std::size_t size() const noexcept { return this->bounds.size(); } }; @@ -945,18 +1022,22 @@ namespace __gnu_test { T* end; - friend bool operator==(const sentinel& s, const I& i) noexcept + friend constexpr + bool operator==(const sentinel& s, const I& i) noexcept { return s.end == i.ptr; } - friend std::iter_difference_t<I> + friend constexpr + std::iter_difference_t<I> operator-(const sentinel& s, const I& i) noexcept { return std::iter_difference_t<I>(s.end - i.ptr); } - friend std::iter_difference_t<I> + friend constexpr + std::iter_difference_t<I> operator-(const I& i, const sentinel& s) noexcept { return std::iter_difference_t<I>(i.ptr - s.end); } }; + constexpr auto end() & { using I = decltype(this->get_iterator(this->bounds.last)); |