diff options
228 files changed, 8657 insertions, 1379 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eebaa03..9a0d334 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,43 @@ +2025-11-02 Jeff Law <jlaw@ventanamicro.com> + + * config/riscv/bitmanip.md (rotrsi3): Use the sign extended form + for 32 bit rotates on TARGET_64BIT, even for constant counts. + * config/riscv/thead.md (th_srrisi3_extended): New pattern. + (th_srri<mode>3): Adjust formatting. + +2025-11-02 Uros Bizjak <ubizjak@gmail.com> + + PR target/122518 + * config/i386/i386.cc (ix86_canonicalize_comparison): Convert + (compare (minus (a b)) a) to (compare (a b)) to + match *sub<mode>_3 pattern. + +2025-11-02 Georg-Johann Lay <avr@gjlay.de> + + PR target/122527 + * config/avr/avr.cc (avr_load_libgcc_p): Return false if + the address-space is not ADDR_SPACE_FLASH. + (avr_out_lpm_no_lpmx [addr=REG]): Handle sizes of 3 and 4 bytes. + +2025-11-02 Georg-Johann Lay <avr@gjlay.de> + + PR tree-optimization/118012 + PR tree-optimization/122505 + * config/avr/avr.md (mulpsi3): Also allow the insn condition + in the case where avropt_pr118012 && !AVR_TINY. + (*mulpsi3): Handle split for the !AVR_HAVE_MUL case. + (*mulpsi3-nomul.libgcc_split, *mulpsi3-nomul.libgcc): New insns. + +2025-11-02 Richard Biener <rguenther@suse.de> + + * doc/tree-ssa.texi: Remove outdated info on FOR_EACH_IMM_USE_STMT + iteration, clarify SSA operand parts. + * ssa-iterators.h: Update toplevel comment. + +2025-11-02 Sam James <sam@gentoo.org> + + * .simplify-rtx.cc.swo: Removed. + 2025-11-01 Shreya Munnangi <smunnangi1@ventanamicro.com> PR target/67731 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index befd735..2bb6e40 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251102 +20251103 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f91fc31..86629f3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,25 @@ +2025-11-02 Eric Botcazou <ebotcazou@adacore.com> + + * locales.c (is_iso_639_3): New static function. + (c_get_language_code): Use it to validate the ISO-639-3 code + before returning it. + +2025-11-02 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/58881 + * sem_ch3.adb (Build_Derived_Private_Type): Build the underlying + full view when the derivation occurs in the public part of the + scope of the parent. + (Build_Derived_Record_Type): Propagate Has_Unknown_Discriminants + in the same circumstances. + (Constrain_Discriminated_Type): Give a specific error message for + any type with the Has_Unknown_Discriminants flag. + +2025-11-02 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/52319 + * sem_ch8.adb (End_Use_Package): Use the scope of the operator. + 2025-10-30 Eric Botcazou <ebotcazou@adacore.com> PR ada/15610 diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads index ab87f54..5d242ed 100644 --- a/gcc/ada/aspects.ads +++ b/gcc/ada/aspects.ads @@ -81,7 +81,6 @@ package Aspects is Aspect_Bit_Order, Aspect_Component_Size, Aspect_Constant_Indexing, - Aspect_Constructor, -- GNAT Aspect_Contract_Cases, -- GNAT Aspect_Convention, Aspect_CPU, @@ -440,7 +439,6 @@ package Aspects is Aspect_Bit_Order => Expression, Aspect_Component_Size => Expression, Aspect_Constant_Indexing => Name, - Aspect_Constructor => Name, Aspect_Contract_Cases => Expression, Aspect_Convention => Name, Aspect_CPU => Expression, @@ -547,7 +545,6 @@ package Aspects is Aspect_Component_Size => True, Aspect_Constant_Indexing => False, Aspect_Contract_Cases => False, - Aspect_Constructor => False, Aspect_Convention => True, Aspect_CPU => False, Aspect_Default_Component_Value => True, @@ -723,7 +720,6 @@ package Aspects is Aspect_Constant_After_Elaboration => Name_Constant_After_Elaboration, Aspect_Constant_Indexing => Name_Constant_Indexing, Aspect_Contract_Cases => Name_Contract_Cases, - Aspect_Constructor => Name_Constructor, Aspect_Convention => Name_Convention, Aspect_CPU => Name_CPU, Aspect_CUDA_Device => Name_CUDA_Device, @@ -997,7 +993,6 @@ package Aspects is Aspect_Asynchronous => Always_Delay, Aspect_Attach_Handler => Always_Delay, Aspect_Constant_Indexing => Always_Delay, - Aspect_Constructor => Always_Delay, Aspect_CPU => Always_Delay, Aspect_CUDA_Device => Always_Delay, Aspect_CUDA_Global => Always_Delay, diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb index 327bc2d..a13438a 100644 --- a/gcc/ada/atree.adb +++ b/gcc/ada/atree.adb @@ -1005,61 +1005,49 @@ package body Atree is Old_Kind : constant Entity_Kind := Ekind (Old_N); - function Same_Node_To_Fetch_From - (N : Node_Or_Entity_Id; Field : Node_Or_Entity_Field) - return Boolean; - -- True if the field should be fetched from N. For most fields, this is - -- true. However, if the field is a "root type only" field, then this is - -- true only if N is the root type. If this is false, then we should not - -- do Reinit_Field_To_Zero, and we should not fail below, because the - -- field is not vanishing from the root type. Similar comments apply to - -- "base type only" and "implementation base type only" fields. - -- - -- We need to ignore exceptions here, because in some cases, - -- Node_To_Fetch_From is being called before the relevant (root, base) - -- type has been set, so we fail some assertions. - - function Same_Node_To_Fetch_From - (N : Node_Or_Entity_Id; Field : Node_Or_Entity_Field) - return Boolean is - begin - return N = Node_To_Fetch_From (N, Field); - exception - when others => return False; -- ignore the exception - end Same_Node_To_Fetch_From; - -- Start of processing for Check_Vanishing_Fields begin for J in Entity_Field_Table (Old_Kind)'Range loop declare F : constant Entity_Field := Entity_Field_Table (Old_Kind) (J); - begin - if not Same_Node_To_Fetch_From (Old_N, F) then - null; -- no check in this case - elsif not Field_Checking.Field_Present (New_Kind, F) then - if not Field_Is_Initial_Zero (Old_N, F) then - Write_Str ("# "); - Write_Str (Osint.Get_First_Main_File_Name); - Write_Str (": "); - Write_Str (Old_Kind'Img); - Write_Str (" --> "); - Write_Str (New_Kind'Img); - Write_Str (" Nonzero field "); - Write_Str (F'Img); - Write_Str (" is vanishing "); - - if New_Kind = E_Void or else Old_Kind = E_Void then - Write_Line ("(E_Void case)"); - else - Write_Line ("(non-E_Void case)"); - end if; + Same_Node_To_Fetch_From : constant Boolean := + Old_N = Node_To_Fetch_From_If_Set (Old_N, F); + -- True if the field F should be fetched from Old_N. For most + -- fields, this is True. However, if F is a "root type only" + -- field, then it should be fetched from the root type, so this is + -- true only if Old_N is the root type. If this is False, then we + -- should not have done Reinit_Field_To_Zero, and we should not + -- fail below, because the field is not vanishing from this node. + -- We use the ..._If_Set function to avoid failing when the root + -- type has not yet been set. Similar comments apply to "base type + -- only" and "implementation base type only" fields. - Write_Str (" ...mutating node "); - Write_Int (Nat (Old_N)); - Write_Line (""); - raise Program_Error; + begin + if Same_Node_To_Fetch_From + and then not Field_Checking.Field_Present (New_Kind, F) + and then not Field_Is_Initial_Zero (Old_N, F) + then + Write_Str ("# "); + Write_Str (Osint.Get_First_Main_File_Name); + Write_Str (": "); + Write_Str (Old_Kind'Img); + Write_Str (" --> "); + Write_Str (New_Kind'Img); + Write_Str (" Nonzero field "); + Write_Str (F'Img); + Write_Str (" is vanishing "); + + if New_Kind = E_Void or else Old_Kind = E_Void then + Write_Line ("(E_Void case)"); + else + Write_Line ("(non-E_Void case)"); end if; + + Write_Str (" ...mutating node "); + Write_Int (Nat (Old_N)); + Write_Line (""); + raise Program_Error; end if; end; end loop; diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index c30e5f1..39cf37e 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -596,9 +596,10 @@ package body Checks is -- Note: we do not check for checks suppressed here, since that check -- was done in Sem_Ch13 when the address clause was processed. We are -- only called if checks were not suppressed. The reason for this is - -- that we have to delay the call to Apply_Alignment_Check till freeze - -- time (so that all types etc are elaborated), but we have to check - -- the status of check suppressing at the point of the address clause. + -- that we have to delay the call to Apply_Address_Clause_Check till + -- freeze time (so that all types etc are elaborated), but we have to + -- check the status of check suppressing at the point of the address + -- clause. if No (AC) or else not Check_Address_Alignment (AC) diff --git a/gcc/ada/cstand.adb b/gcc/ada/cstand.adb index cdf2b5d..8dd169a 100644 --- a/gcc/ada/cstand.adb +++ b/gcc/ada/cstand.adb @@ -298,6 +298,7 @@ package body CStand is Build_Float_Type (To, UI_To_Int (Digits_Value (From)), Float_Rep (From), UI_To_Int (Esize (From)), UI_To_Int (Alignment (From))); + Set_Is_IEEE_Extended_Precision (To, Is_IEEE_Extended_Precision (From)); end Copy_Float_Type; ---------------------- @@ -2100,17 +2101,22 @@ package body CStand is Size : Positive; Alignment : Natural) is - pragma Unreferenced (Precision); - -- See Build_Float_Type for the rationale - Ent : constant Entity_Id := New_Standard_Entity (Name); + IEEE_Extended_Precision_Size : constant := 80; begin Set_Defining_Identifier (New_Node (N_Full_Type_Declaration, Stloc), Ent); Set_Scope (Ent, Standard_Standard); Build_Float_Type (Ent, Pos (Digs), Float_Rep, Int (Size), Nat (Alignment / 8)); + -- We mostly disregard Precision, see Build_Float_Type for the + -- rationale. The only thing we use it for is to detect 80-bit IEEE + -- extended precision, in order to adjust the behavior of 'Write. + if Precision = IEEE_Extended_Precision_Size then + Set_Is_IEEE_Extended_Precision (Ent); + end if; + Append_New_Elmt (Ent, Back_End_Float_Types); end Register_Float_Type; diff --git a/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst b/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst index 7250f65..65bb187 100644 --- a/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst @@ -1580,8 +1580,7 @@ machines with strict alignment requirements, GNAT checks (at compile time if possible, generating a warning, or at execution time with a run-time check) that the alignment is appropriate. If the run-time check fails, then ``Program_Error`` is raised. This run-time -check is suppressed if range checks are suppressed, or if the special GNAT -check Alignment_Check is suppressed, or if +check is suppressed if the GNAT check Alignment_Check is suppressed, or if ``pragma Restrictions (No_Elaboration_Code)`` is in effect. It is also suppressed by default on non-strict alignment machines (such as the x86). diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb index b0acb25..6d10a7f 100644 --- a/gcc/ada/einfo-utils.adb +++ b/gcc/ada/einfo-utils.adb @@ -2622,13 +2622,20 @@ package body Einfo.Utils is begin return T : Opt_N_Entity_Id := Base_Type_If_Set (Id) do - if Ekind (T) = E_Class_Wide_Type then + if No (T) then + null; + elsif Ekind (T) = E_Class_Wide_Type then T := Etype (T); else loop Etyp := Etype (T); - exit when No (Etyp) or else T = Etyp + if No (Etyp) then + T := Empty; + exit; + end if; + + exit when T = Etyp or else (Is_Private_Type (T) and then Etyp = Full_View (T)) or else @@ -3086,7 +3093,7 @@ package body Einfo.Utils is elsif Ekind (Id) = E_Class_Wide_Type and then From_Limited_With (Id) - and then Present (Non_Limited_View (Id)) + and then Has_Non_Limited_View (Id) then return Underlying_Type (Non_Limited_View (Id)); @@ -3118,7 +3125,7 @@ package body Einfo.Utils is -- then we return the Underlying_Type of its nonlimited view. elsif From_Limited_With (Id) - and then Present (Non_Limited_View (Id)) + and then Has_Non_Limited_View (Id) then return Underlying_Type (Non_Limited_View (Id)); diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index b9548a7..8e41d0f 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -1585,11 +1585,11 @@ package Einfo is -- type derivation. -- Has_Delayed_Aspects --- Defined in all entities. Set if the Rep_Item chain for the entity has --- one or more N_Aspect_Definition nodes chained which are not to be --- evaluated till the freeze point. The aspect definition expression --- clause has been preanalyzed to get visibility at the point of use, --- but no other action has been taken. +-- Defined in all entities. Set if the Rep_Item chain for the entity has +-- one or more N_Aspect_Definition nodes chained which are not to be +-- evaluated till the freeze point. The aspect definition expression +-- clause has been preanalyzed to get visibility at the point of use, +-- but no other action has been taken. -- Has_Delayed_Freeze -- Defined in all entities. Set to indicate that an explicit freeze @@ -1889,10 +1889,6 @@ package Einfo is -- 5. N_Range_Constraint - when the range expression uses the -- discriminant of the enclosing type. --- Has_Pragma_Controlled [implementation base type only] --- Defined in access type entities. It is set if a pragma Controlled --- applies to the access type. - -- Has_Pragma_Elaborate_Body -- Defined in all entities. Set in compilation unit entities if a -- pragma Elaborate_Body applies to the compilation unit. @@ -2383,7 +2379,7 @@ package Einfo is -- Is_Activation_Record -- Applies to E_In_Parameters generated in Exp_Unst for nested -- subprograms, to mark the added formal that carries the activation --- record created in the enclosing subprogram. +-- record created in the enclosing subprogram. Used by the llvm back end. -- Is_Actual_Subtype -- Defined on all types, true for the generated constrained subtypes @@ -2596,7 +2592,7 @@ package Einfo is -- Is_Discriminant_Check_Function -- Defined in all entities. Set only in E_Function entities for functions --- created to do discriminant checks. +-- created to do discriminant checks. Used by CodePeer. -- Is_Discriminal (synthesized) -- Applies to all entities, true for renamings of discriminants. Such @@ -3471,10 +3467,6 @@ package Einfo is -- as its corresponding record type, but whose parent is the full view -- of the parent in the original type extension. --- Is_Unimplemented --- Defined in all entities. Set for any entity to which a valid pragma --- or aspect Unimplemented applies. - -- Is_Unsigned_Type -- Defined in all types, but can be set only for discrete and fixed-point -- type and subtype entities. This flag is only valid if the entity is @@ -3552,6 +3544,15 @@ package Einfo is -- a wrapper to handle inherited class-wide pre/post conditions that call -- overridden primitives or as a wrapper of a controlling function. +-- Is_IEEE_Extended_Precision +-- Defined in floating point types and subtypes. Indicates that the type +-- corresponds to the 80-bit IEEE extended precision format. That format +-- effectively uses 80 bits per value, but we set its Size to a larger +-- value for the reasons explained in the documentation comment of +-- Build_Float_Type. We also perform some extra work to consistently set +-- the extra bits to zero in the 'Write implementation, which is why we +-- need this flag. + -- Itype_Printed -- Defined in all type and subtype entities. Set in Itypes if the Itype -- has been printed by Sprint. This is used to avoid printing an Itype @@ -3705,6 +3706,11 @@ package Einfo is -- preelaborable initialization at freeze time (this has to be deferred -- to the freeze point because of the rule about overriding Initialize). +-- Needs_Construction +-- Defined in all type and subtype entities. Set only for record type +-- entities for which at least one ancestor has specified a constructor +-- through the 'Constructor direct attribute definition. + -- Needs_Debug_Info -- Defined in all entities. Set if the entity requires normal debugging -- information to be generated. This is true of all entities that have @@ -5018,7 +5024,6 @@ package Einfo is -- Is_Thunk -- Is_Trivial_Subprogram -- Is_Unchecked_Union - -- Is_Unimplemented -- Is_Visible_Formal -- Kill_Elaboration_Checks -- Low_Bound_Tested @@ -5130,6 +5135,7 @@ package Einfo is -- May_Inherit_Delayed_Rep_Aspects -- Must_Be_On_Byte_Boundary -- Must_Have_Preelab_Init + -- Needs_Construction -- Optimize_Alignment_Space -- Optimize_Alignment_Time -- Partial_View_Has_Unknown_Discr @@ -5211,7 +5217,6 @@ package Einfo is -- Associated_Storage_Pool (root type only) -- Finalization_Collection (root type only) -- Storage_Size_Variable (base type only) - -- Has_Pragma_Controlled (base type only) -- Has_Storage_Size_Clause (base type only) -- Is_Access_Constant -- Is_Local_Anonymous_Access @@ -5529,6 +5534,7 @@ package Einfo is -- Digits_Value -- Float_Rep (Float_Rep_Kind) -- Default_Aspect_Value (base type only) + -- Is_IEEE_Extended_Precision -- Scalar_Range -- Static_Real_Or_String_Predicate -- Machine_Emax_Value (synth) diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb index 472fbbe..220523c 100644 --- a/gcc/ada/errout.adb +++ b/gcc/ada/errout.adb @@ -163,8 +163,8 @@ package body Errout is procedure Set_Msg_Node (Node : Node_Id); -- Add the sequence of characters for the name associated with the given -- node to the current message. For N_Designator, N_Selected_Component, - -- N_Defining_Program_Unit_Name, and N_Expanded_Name, the Prefix is - -- included as well. + -- N_Defining_Program_Unit_Name, N_Expanded_Name, and N_Attribute_Reference + -- the Prefix is included as well. procedure Set_Posted (N : Node_Id); -- Sets the Error_Posted flag on the given node, and all its parents that @@ -3800,6 +3800,29 @@ package body Errout is Set_Msg_Node (Selector_Name (Node)); return; + when N_Attribute_Reference => + Set_Msg_Node (Prefix (Node)); + Set_Msg_Char ('''); + Get_Unqualified_Decoded_Name_String (Attribute_Name (Node)); + Adjust_Name_Case (Global_Name_Buffer, Sloc (Node)); + Set_Msg_Name_Buffer; + return; + + when N_Defining_Identifier => + + -- Handle direct attribute definitions + + if Parent_Kind (Node) in N_Subprogram_Specification + and then Original_Node (Parent (Node)) /= Parent (Node) + and then Nkind (Defining_Unit_Name + (Original_Node (Parent (Node)))) + = N_Attribute_Reference + then + Set_Msg_Node + (Defining_Unit_Name (Original_Node (Parent (Node)))); + return; + end if; + when others => null; end case; diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb index 14a11ff..bbbe245 100644 --- a/gcc/ada/erroutc.adb +++ b/gcc/ada/erroutc.adb @@ -1579,6 +1579,46 @@ package body Erroutc is ---------------------------- procedure Set_Msg_Insertion_Name is + procedure Replace_With_Attribute_Definition; + -- This procedure handles direct attribute definition names of the form: + -- 'D' Prefix_Name "_" Attribute_Name "_Att" + -- Specifically, it replace the current Namet.Global_Name_Buffer with an + -- all lowercase string of the prefix, and a tick attribute; at this + -- stage there is no way to recognize more than an ending attribute ??? + -- + -- Note that, at this point, it is not possible to restore the original + -- casing thus lowercase is default.a + + procedure Replace_With_Attribute_Definition is + First : constant Integer := 2; + Last : constant Integer := Name_Len - 4; + Att_Buf : Bounded_String (Max_Length => Name_Len - 7); + begin + Until_Tick : + for J in First .. Last loop + + -- J could be at the position separating the prefix from the + -- attribute name. + + if Name_Buffer (J) = '_' then + Att_Buf.Length := 0; + Append (Att_Buf, Name_Buffer (J + 1 .. Last)); + Set_Casing (Att_Buf, All_Lower_Case); + if Is_Direct_Attribute_Definition_Name (Name_Find (Att_Buf)) + then + Name_Buffer (J) := '''; + exit Until_Tick; + end if; + end if; + end loop Until_Tick; + + -- Remove prefix 'D' and suffix "_Att" + + Name_Buffer (1 .. Last - 1) := Name_Buffer (2 .. Last); + Name_Len := Last - 1; + Set_Casing (All_Lower_Case); + end Replace_With_Attribute_Definition; + begin if Error_Msg_Name_1 = No_Name then null; @@ -1624,7 +1664,14 @@ package body Erroutc is -- Else output with surrounding quotes in proper casing mode else - Set_Casing (Identifier_Casing (Flag_Source)); + if Name_Buffer (1) = 'D' + and then Name_Buffer (Name_Len - 3 .. Name_Len) = "_Att" + then + Replace_With_Attribute_Definition; + else + Set_Casing (Identifier_Casing (Flag_Source)); + end if; + Set_Msg_Quote; Set_Msg_Name_Buffer; Set_Msg_Quote; diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index d62b735..6b6b0ab 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -4914,11 +4914,10 @@ package body Exp_Aggr is -- IP procedure. if Has_Default_Init_Comps (N) - or else Present (Constructor_Name (Ctyp)) + or else Needs_Construction (Ctyp) or else (Is_Access_Type (Ctyp) - and then Present - (Constructor_Name - (Directly_Designated_Type (Ctyp)))) + and then Needs_Construction + (Directly_Designated_Type (Ctyp))) then return; end if; diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index a0a550d..086ef91 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -1906,6 +1906,9 @@ package body Exp_Attr is function Get_Integer_Type (Typ : Entity_Id) return Entity_Id; -- Return a small integer type appropriate for the enumeration type + function Get_Array_Stream_Item_Type (Typ : Entity_Id) return Entity_Id; + -- For non-scalar types return the first subtype of Typ. + procedure Rewrite_Attribute_Proc_Call (Pname : Entity_Id); -- Rewrites an attribute for Read, Write, Output, or Put_Image with a -- call to the appropriate TSS procedure. Pname is the entity for the @@ -2066,6 +2069,19 @@ package body Exp_Attr is return Small_Integer_Type_For (Siz, Uns => Is_Unsigned_Type (Typ)); end Get_Integer_Type; + -------------------------------- + -- Get_Array_Stream_Item_Type -- + -------------------------------- + + function Get_Array_Stream_Item_Type (Typ : Entity_Id) return Entity_Id is + First_Sub_Typ : constant Entity_Id := First_Subtype (Typ); + begin + if Is_Private_Type (First_Sub_Typ) then + return Typ; + end if; + return First_Sub_Typ; + end Get_Array_Stream_Item_Type; + --------------------------------- -- Rewrite_Attribute_Proc_Call -- --------------------------------- @@ -4482,6 +4498,7 @@ package body Exp_Attr is P_Type : constant Entity_Id := Entity (Pref); B_Type : constant Entity_Id := Base_Type (P_Type); U_Type : constant Entity_Id := Underlying_Type (P_Type); + I_Type : Entity_Id := P_Type; Strm : constant Node_Id := First (Exprs); Fname : Entity_Id; Decl : Node_Id; @@ -4633,8 +4650,9 @@ package body Exp_Attr is new Build_And_Insert_Type_Attr_Subp (Build_Array_Input_Function); begin + I_Type := Get_Array_Stream_Item_Type (U_Type); Build_And_Insert_Array_Input_Func - (Typ => Full_Base (U_Type), + (Typ => I_Type, Decl => Decl, Subp => Fname, Attr_Ref => N); @@ -4784,8 +4802,13 @@ package body Exp_Attr is Relocate_Node (Strm))); Set_Controlling_Argument (Call, Cntrl); - Rewrite (N, Unchecked_Convert_To (P_Type, Call)); - Analyze_And_Resolve (N, P_Type); + if Is_Private_Type (P_Type) or else Is_Class_Wide_Type (P_Type) then + Rewrite (N, Unchecked_Convert_To (P_Type, Call)); + Analyze_And_Resolve (N, P_Type); + else + Rewrite (N, Call); + Analyze_And_Resolve (N, I_Type); + end if; if Nkind (Parent (N)) = N_Object_Declaration then Freeze_Stream_Subprogram (Fname); @@ -5142,7 +5165,8 @@ package body Exp_Attr is Make_Selected_Component (Loc, Prefix => New_Occurrence_Of (Result_Id, Loc), Selector_Name => Make_Identifier (Loc, - Chars (Constructor_Name (Typ)))); + Direct_Attribute_Definition_Name + (Typ, Name_Constructor))); begin Set_Is_Prefixed_Call (Proc_Name); @@ -5818,7 +5842,7 @@ package body Exp_Attr is (Build_Array_Output_Procedure); begin Build_And_Insert_Array_Output_Proc - (Typ => Full_Base (U_Type), + (Typ => Get_Array_Stream_Item_Type (U_Type), Decl => Decl, Subp => Pname, Attr_Ref => N); @@ -6280,7 +6304,7 @@ package body Exp_Attr is /= RTU_Entity (Interfaces_C)) then Rewrite (N, Build_String_Put_Image_Call (N)); - Analyze (N); + Analyze (N, Suppress => All_Checks); return; elsif Is_Array_Type (U_Type) then @@ -6295,10 +6319,10 @@ package body Exp_Attr is begin Build_And_Insert_Array_Put_Image_Proc - (Typ => U_Type, + (Typ => Get_Array_Stream_Item_Type (U_Type), Decl => Decl, - Subp => Pname, - Attr_Ref => N); + Subp => Pname, + Attr_Ref => N); end; Cached_Attribute_Ops.Put_Image_Map.Set (U_Type, Pname); @@ -6746,7 +6770,7 @@ package body Exp_Attr is (Build_Array_Read_Procedure); begin Build_And_Insert_Array_Read_Proc - (Typ => Full_Base (U_Type), + (Typ => Get_Array_Stream_Item_Type (U_Type), Decl => Decl, Subp => Pname, Attr_Ref => N); @@ -8461,7 +8485,7 @@ package body Exp_Attr is (Build_Array_Write_Procedure); begin Build_And_Insert_Array_Write_Proc - (Typ => Full_Base (U_Type), + (Typ => Get_Array_Stream_Item_Type (U_Type), Decl => Decl, Subp => Pname, Attr_Ref => N); @@ -8577,6 +8601,7 @@ package body Exp_Attr is | Attribute_Bit_Order | Attribute_Class | Attribute_Compiler_Version + | Attribute_Constructor | Attribute_Default_Bit_Order | Attribute_Default_Scalar_Storage_Order | Attribute_Definite diff --git a/gcc/ada/exp_ch11.adb b/gcc/ada/exp_ch11.adb index ee6010a7..a6b1718 100644 --- a/gcc/ada/exp_ch11.adb +++ b/gcc/ada/exp_ch11.adb @@ -1031,7 +1031,7 @@ package body Exp_Ch11 is -- "hoisted" (i.e., Is_Statically_Allocated and not Is_Library_Level) -- entity must also be either Library_Level or hoisted. It turns out -- that this would be incompatible with the current treatment of an - -- object which is local to a subprogram, subject to an Export pragma, + -- object that is local to a subprogram, subject to an Export pragma, -- not subject to an address clause, and whose declaration contains -- references to other local (non-hoisted) objects (e.g., in the initial -- value expression). @@ -1558,7 +1558,7 @@ package body Exp_Ch11 is Build_Location_String (Buf, Loc); -- If the exception is a renaming, use the exception that it - -- renames (which might be a predefined exception, e.g.). + -- renames (which might be a predefined exception). if Present (Renamed_Entity (Id)) then Id := Renamed_Entity (Id); diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 60224c1..db41ab7 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -3185,8 +3185,8 @@ package body Exp_Ch3 is if Parent_Subtype_Renaming_Discrims then Append_List_To (Body_Stmts, Build_Init_Call_Thru (Parameters)); - elsif Present (Constructor_Name (Rec_Type)) then - if Present (Default_Constructor (Rec_Type)) then + elsif Needs_Construction (Rec_Type) then + if Has_Default_Constructor (Rec_Type) then -- The 'Make attribute reference (with no arguments) will -- generate a call to the one-parameter constructor procedure. @@ -3810,8 +3810,8 @@ package body Exp_Ch3 is -- Expand components with constructors to have the 'Make -- attribute. - elsif Present (Constructor_Name (Typ)) - and then Present (Default_Constructor (Typ)) + elsif Needs_Construction (Typ) + and then Has_Default_Constructor (Typ) then Set_Expression (Decl, Make_Attribute_Reference (Loc, @@ -4560,7 +4560,7 @@ package body Exp_Ch3 is -- since the call is generated, there had better be a routine -- at the other end of the call, even if it does nothing). - -- 10. The type has a specified Constructor aspect. + -- 10. The type needs construction with constructors. -- Note: the reason we exclude the CPP_Class case is because in this -- case the initialization is performed by the C++ constructors, and @@ -4577,7 +4577,7 @@ package body Exp_Ch3 is or else Is_Tagged_Type (Rec_Id) or else Is_Concurrent_Record_Type (Rec_Id) or else Has_Task (Rec_Id) - or else Present (Constructor_Name (Rec_Id)) + or else Needs_Construction (Rec_Id) then return True; end if; @@ -7587,8 +7587,8 @@ package body Exp_Ch3 is if No (Expr) and then Constant_Present (N) - and then (No (Constructor_Name (Typ)) - or else No (Default_Constructor (Typ))) + and then (not Needs_Construction (Typ) + or else not Has_Default_Constructor (Typ)) then return; end if; @@ -7619,8 +7619,8 @@ package body Exp_Ch3 is if Comes_From_Source (N) and then No (Expr) - and then Present (Constructor_Name (Typ)) - and then Present (Default_Constructor (Typ)) + and then Needs_Construction (Typ) + and then Has_Default_Constructor (Typ) then Expr := Make_Attribute_Reference (Loc, Attribute_Name => Name_Make, @@ -8286,6 +8286,16 @@ package body Exp_Ch3 is Set_Must_Not_Freeze (Id_Ref); Set_Assignment_OK (Id_Ref); + -- Avoid separating an object declaration from + -- its representation clauses. + + while Present (Next (Init_After)) + and then Nkind (Next (Init_After)) in + N_Attribute_Definition_Clause + loop + Init_After := Next (Init_After); + end loop; + Insert_Actions_After (Init_After, Build_Initialization_Call (N, Id_Ref, Typ, Constructor_Ref => Expr)); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 8fba1c4..5971db3 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -1432,46 +1432,48 @@ package body Exp_Ch4 is -- For (a <= b) we convert to not (a > b) - if Chars (N) = Name_Op_Le then - Rewrite (N, - Make_Op_Not (Loc, - Right_Opnd => - Make_Op_Gt (Loc, - Left_Opnd => Op1, - Right_Opnd => Op2))); - Analyze_And_Resolve (N, Standard_Boolean); - return; + case Nkind (N) is + when N_Op_Le => + Rewrite (N, + Make_Op_Not (Loc, + Right_Opnd => + Make_Op_Gt (Loc, + Left_Opnd => Op1, + Right_Opnd => Op2))); + Analyze_And_Resolve (N, Standard_Boolean); + return; - -- For < the Boolean expression is - -- greater__nn (op2, op1) + -- For < the Boolean expression is + -- greater__nn (op2, op1) - elsif Chars (N) = Name_Op_Lt then - Func_Body := Make_Array_Comparison_Op (Typ1, N); + when N_Op_Lt => + Func_Body := Make_Array_Comparison_Op (Typ1, N); - -- Switch operands + -- Switch operands - Op1 := Right_Opnd (N); - Op2 := Left_Opnd (N); + Op1 := Right_Opnd (N); + Op2 := Left_Opnd (N); - -- For (a >= b) we convert to not (a < b) + -- For (a >= b) we convert to not (a < b) - elsif Chars (N) = Name_Op_Ge then - Rewrite (N, - Make_Op_Not (Loc, - Right_Opnd => - Make_Op_Lt (Loc, - Left_Opnd => Op1, - Right_Opnd => Op2))); - Analyze_And_Resolve (N, Standard_Boolean); - return; + when N_Op_Ge => + Rewrite (N, + Make_Op_Not (Loc, + Right_Opnd => + Make_Op_Lt (Loc, + Left_Opnd => Op1, + Right_Opnd => Op2))); + Analyze_And_Resolve (N, Standard_Boolean); + return; - -- For > the Boolean expression is - -- greater__nn (op1, op2) + -- For > the Boolean expression is + -- greater__nn (op1, op2) - else - pragma Assert (Chars (N) = Name_Op_Gt); - Func_Body := Make_Array_Comparison_Op (Typ1, N); - end if; + when N_Op_Gt => + Func_Body := Make_Array_Comparison_Op (Typ1, N); + + when others => raise Program_Error; + end case; Func_Name := Defining_Unit_Name (Specification (Func_Body)); Expr := @@ -4496,7 +4498,7 @@ package body Exp_Ch4 is -- Here we set no initialization on types with constructors since we -- generate initialization for the separately. - if Present (Constructor_Name (Directly_Designated_Type (PtrT))) + if Needs_Construction (Directly_Designated_Type (PtrT)) and then Nkind (Expression (N)) = N_Identifier then Set_No_Initialization (N, False); diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index d48b8f2..d209ab0 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -6250,9 +6250,9 @@ package body Exp_Ch6 is procedure Prepend_Constructor_Procedure_Prologue (Spec_Id : Entity_Id; Body_Id : Entity_Id; L : List_Id); -- If N is the body of a constructor procedure (that is, a procedure - -- named in a Constructor aspect specification for the type of the - -- procedure's first parameter), then prepend and analyze the - -- associated initialization code for that parameter. + -- named T'Constructor where T is the type of the procedure's first + -- parameter), then prepend and analyze the associated initialization + -- code for that parameter. -- This has nothing to do with CPP constructors. ---------------- @@ -6339,16 +6339,10 @@ package body Exp_Ch6 is function First_Param_Type return Entity_Id is (Implementation_Base_Type (Etype (First_Formal (Spec_Id)))); - Is_Constructor_Procedure : constant Boolean := - Nkind (Specification (N)) = N_Procedure_Specification - and then Present (First_Formal (Spec_Id)) - and then Present (Constructor_Name (First_Param_Type)) - and then Chars (Spec_Id) = Chars (Constructor_Name - (First_Param_Type)) - and then Ekind (First_Formal (Spec_Id)) = E_In_Out_Parameter - and then Scope (Spec_Id) = Scope (First_Param_Type); begin - if not Is_Constructor_Procedure then + if not (Nkind (Specification (N)) = N_Procedure_Specification + and then Is_Constructor_Procedure (Spec_Id)) + then return; -- the usual case end if; @@ -6539,7 +6533,8 @@ package body Exp_Ch6 is Attribute_Name => Name_Super), Selector_Name => Make_Identifier (Loc, - Chars (Constructor_Name (Parent_Type)))); + Direct_Attribute_Definition_Name + (Parent_Type, Name_Constructor))); begin Set_Is_Prefixed_Call (Proc_Name); @@ -9096,27 +9091,6 @@ package body Exp_Ch6 is -- tagged, the called function itself must perform the allocation of -- the return object, so we pass parameters indicating that. - -- But that's also the case when the result subtype needs finalization - -- actions because the caller side allocation may result in undesirable - -- finalization. Consider the following example: - -- - -- function Make_Lim_Ctrl return Lim_Ctrl is - -- begin - -- return Result : Lim_Ctrl := raise Program_Error do - -- null; - -- end return; - -- end Make_Lim_Ctrl; - -- - -- Obj : Lim_Ctrl_Ptr := new Lim_Ctrl'(Make_Lim_Ctrl); - -- - -- Even though the size of limited controlled type Lim_Ctrl is known, - -- allocating Obj at the caller side will chain Obj on Lim_Ctrl_Ptr's - -- finalization collection. The subsequent call to Make_Lim_Ctrl will - -- fail during the initialization actions for Result, which means that - -- Result (and Obj by extension) should not be finalized. However Obj - -- will be finalized when access type Lim_Ctrl_Ptr goes out of scope - -- since it is already attached on the its finalization collection. - if Needs_BIP_Alloc_Form (Function_Id) then Temp_Init := Empty; @@ -9281,11 +9255,7 @@ package body Exp_Ch6 is end if; end; - -- When the function has a controlling result, an allocation-form - -- parameter must be passed indicating that the caller is allocating - -- the result object. This is needed because such a function can be - -- called as a dispatching operation and must be treated similarly - -- to functions with unconstrained result subtypes. + -- Add implicit actuals for the BIP formal parameters, if any Add_Unconstrained_Actuals_To_Build_In_Place_Call (Func_Call, @@ -9310,6 +9280,14 @@ package body Exp_Ch6 is Add_Access_Actual_To_Build_In_Place_Call (Func_Call, Function_Id, Return_Obj_Actual); + -- If the allocation is done in the caller, create a custom Allocate + -- procedure if need be. + + if not Needs_BIP_Alloc_Form (Function_Id) then + Build_Allocate_Deallocate_Proc + (Declaration_Node (Return_Obj_Access), Mark => Allocator); + end if; + -- Finally, replace the allocator node with a reference to the temp Rewrite (Allocator, New_Occurrence_Of (Return_Obj_Access, Loc)); @@ -9771,7 +9749,7 @@ package body Exp_Ch6 is -- ensure that the heap allocation can properly chain the object -- and later finalize it when the library unit goes out of scope. - if Needs_BIP_Collection (Func_Call) then + if Needs_BIP_Collection (Function_Id) then Build_Finalization_Collection (Typ => Ptr_Typ, For_Lib_Level => True, @@ -10334,6 +10312,12 @@ package body Exp_Ch6 is Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id)); begin + -- No need for BIP_Collection if allocation is always done in the caller + + if not Needs_BIP_Alloc_Form (Func_Id) then + return False; + end if; + -- A formal for the finalization collection is needed for build-in-place -- functions whose result type needs finalization or is a tagged type. -- Tagged primitive build-in-place functions need such a formal because @@ -10358,12 +10342,6 @@ package body Exp_Ch6 is Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id)); begin - -- See Make_Build_In_Place_Call_In_Allocator for the rationale - - if Needs_BIP_Collection (Func_Id) then - return True; - end if; - -- A formal giving the allocation method is needed for build-in-place -- functions whose result type is returned on the secondary stack or -- is a tagged type. Tagged primitive build-in-place functions need diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads index 5919627..3867270 100644 --- a/gcc/ada/exp_ch6.ads +++ b/gcc/ada/exp_ch6.ads @@ -301,10 +301,8 @@ package Exp_Ch6 is -- BIP_Alloc_Form parameter (see type BIP_Formal_Kind). function Needs_BIP_Collection (Func_Id : Entity_Id) return Boolean; - -- Ada 2005 (AI-318-02): Return True if the result subtype of function - -- Func_Id might need finalization actions. This includes build-in-place - -- functions with tagged result types, since they can be invoked via - -- dispatching calls, and descendant types may require finalization. + -- Ada 2005 (AI-318-02): Return True if the function needs an implicit + -- BIP_Collection parameter (see type BIP_Formal_Kind). function Needs_BIP_Task_Actuals (Func_Id : Entity_Id) return Boolean; -- Return True if the function returns an object of a type that has tasks. diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 62e9d2c..600d333 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -4758,18 +4758,18 @@ package body Exp_Ch7 is -- We mark the secondary stack if it is used in this construct, and -- we're not returning a function result on the secondary stack, except - -- that a build-in-place function that might or might not return on the - -- secondary stack always needs a mark. A run-time test is required in - -- the case where the build-in-place function has a BIP_Alloc extra - -- parameter (see Create_Finalizer). + -- that a build-in-place function that only conditionally returns on + -- the secondary stack will also need a mark. A run-time test for doing + -- the release call is needed in the case where the build-in-place + -- function has a BIP_Alloc_Form parameter (see Create_Finalizer). Needs_Sec_Stack_Mark : constant Boolean := - (Uses_Sec_Stack (Scop) - and then - not Sec_Stack_Needed_For_Return (Scop)) - or else - (Is_Build_In_Place_Function (Scop) - and then Needs_BIP_Alloc_Form (Scop)); + Uses_Sec_Stack (Scop) + and then + (not Sec_Stack_Needed_For_Return (Scop) + or else + (Is_Build_In_Place_Function (Scop) + and then Needs_BIP_Alloc_Form (Scop))); Needs_Custom_Cleanup : constant Boolean := Nkind (N) = N_Block_Statement @@ -9244,7 +9244,7 @@ package body Exp_Ch7 is procedure Unnest_Loop (Loop_Stmt : Node_Id) is - procedure Fixup_Inner_Scopes (Loop_Or_Block : Node_Id); + procedure Fixup_Inner_Scopes (N : Node_Id); -- This procedure fixes the scope for 2 identified cases of incorrect -- scope information. -- @@ -9271,6 +9271,9 @@ package body Exp_Ch7 is -- leaves the Tree in an incoherent state (i.e. the inner procedure must -- have its enclosing procedure in its scope ancestries). + -- The same issue exists for freeze nodes with associated TSS: the node + -- is moved but the TSS procedures are not correctly nested. + -- 2) The second case happens when an object declaration is created -- within a loop used to initialize the 'others' components of an -- aggregate that is nested within a transient scope. When the transient @@ -9298,40 +9301,62 @@ package body Exp_Ch7 is -- an actual entity set). But unfortunately this proved harder to -- implement ??? - procedure Fixup_Inner_Scopes (Loop_Or_Block : Node_Id) is - Stmt : Node_Id; - Loop_Or_Block_Ent : Entity_Id; - Ent_To_Fix : Entity_Id; - Decl : Node_Id := Empty; + procedure Fixup_Inner_Scopes (N : Node_Id) is + Stmt : Node_Id := Empty; + Ent : Entity_Id; + Ent_To_Fix : Entity_Id; + Decl : Node_Id := Empty; + Elmt : Elmt_Id := No_Elmt; begin - pragma Assert (Nkind (Loop_Or_Block) in - N_Loop_Statement | N_Block_Statement); - - Loop_Or_Block_Ent := Entity (Identifier (Loop_Or_Block)); - if Nkind (Loop_Or_Block) = N_Loop_Statement then - Stmt := First (Statements (Loop_Or_Block)); - else -- N_Block_Statement - Stmt := First - (Statements (Handled_Statement_Sequence (Loop_Or_Block))); - Decl := First (Declarations (Loop_Or_Block)); + pragma + Assert + (Nkind (N) + in N_Loop_Statement | N_Block_Statement | N_Freeze_Entity); + + if Nkind (N) = N_Freeze_Entity then + Ent := Scope (Entity (N)); + else + Ent := Entity (Identifier (N)); end if; + case Nkind (N) is + when N_Loop_Statement => + Stmt := First (Statements (N)); + + when N_Block_Statement => + Stmt := First (Statements (Handled_Statement_Sequence (N))); + Decl := First (Declarations (N)); + + when N_Freeze_Entity => + if Present (TSS_Elist (N)) then + Elmt := First_Elmt (TSS_Elist (N)); + while Present (Elmt) loop + Ent_To_Fix := Node (Elmt); + Set_Scope (Ent_To_Fix, Ent); + Next_Elmt (Elmt); + end loop; + end if; + + when others => + pragma Assert (False); + end case; + -- Fix scopes for any object declaration found in the block while Present (Decl) loop if Nkind (Decl) = N_Object_Declaration then Ent_To_Fix := Defining_Identifier (Decl); - Set_Scope (Ent_To_Fix, Loop_Or_Block_Ent); + Set_Scope (Ent_To_Fix, Ent); end if; Next (Decl); end loop; while Present (Stmt) loop - if Nkind (Stmt) = N_Block_Statement - and then Is_Abort_Block (Stmt) + if Nkind (Stmt) = N_Block_Statement and then Is_Abort_Block (Stmt) then Ent_To_Fix := Entity (Identifier (Stmt)); - Set_Scope (Ent_To_Fix, Loop_Or_Block_Ent); - elsif Nkind (Stmt) in N_Block_Statement | N_Loop_Statement + Set_Scope (Ent_To_Fix, Ent); + elsif Nkind (Stmt) + in N_Block_Statement | N_Loop_Statement | N_Freeze_Entity then Fixup_Inner_Scopes (Stmt); end if; diff --git a/gcc/ada/exp_dbug.ads b/gcc/ada/exp_dbug.ads index 1a64888..0786c40 100644 --- a/gcc/ada/exp_dbug.ads +++ b/gcc/ada/exp_dbug.ads @@ -193,6 +193,25 @@ package Exp_Dbug is -- extra__messages__Oeq__2 ---------------------------------- + -- Direct Attribute Definitions -- + ---------------------------------- + + -- Direct attribute definitions are subprogram declarations where the + -- subprogram name is an attribute reference, eg.: + -- procedure T'Constructor (Self... + -- defines a constructor. The above rules applied to direct attribute + -- definitions would result in names with quotation marks, which are + -- typically hard to deal with down the chain. To avoid this problem, + -- names of such definitions are encoded with as: + + -- 'D' Prefix_Name '_' Attribute_Name "_Att" + + -- For instance, the constructor above is encoded as Dt_constructor_Att. + + -- Note that, attribute reference with multiple attributes are not + -- supported yet ??? + + ---------------------------------- -- Resolving Other Name Clashes -- ---------------------------------- diff --git a/gcc/ada/exp_strm.adb b/gcc/ada/exp_strm.adb index 3bb6966..f933a2e 100644 --- a/gcc/ada/exp_strm.adb +++ b/gcc/ada/exp_strm.adb @@ -501,6 +501,14 @@ package body Exp_Strm is then return Prims (RE_I_LF, RE_W_LF); + elsif Is_IEEE_Extended_Precision (U_Type) then + -- For 80-bit IEEE extended precision values, we use a special + -- write routine that sets the unused bytes to zero. The reason + -- why we don't set Stream_Size to 80 and stream only the + -- meaningful bits is that the user is allowed to select the XDR + -- implementation of streaming at bind time, and XDR does not + -- allow 80 bits floating point values. + return Prims (RE_I_LLF, RE_W_80IEEE); elsif P_Size = Standard_Long_Long_Float_Size then return Prims (RE_I_LLF, RE_W_LLF); else diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb index 58f6689..9a1ed70 100644 --- a/gcc/ada/exp_unst.adb +++ b/gcc/ada/exp_unst.adb @@ -220,6 +220,8 @@ package body Exp_Unst is else Lev := Lev + 1; S := Enclosing_Subprogram (S); + + pragma Assert (Present (S)); end if; end loop; end Get_Level; diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 4d88626..e2d2554 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -7317,6 +7317,134 @@ package body Exp_Util is Loc : constant Source_Ptr := Sloc (Var); Ent : constant Entity_Id := Entity (Var); + procedure Find_In_Enclosing_Context + (Stmt : Node_Id; Current, Previous : in out Node_Id); + -- Locate an object reference inside a composite statement Stmt. On + -- entry, Previous and Current should be an object reference and its + -- parent, respectively. When search is successful, Current is Stmt and + -- Previous is its child node, so the caller can determine in which part + -- of the statement the original reference was. When search fails, both + -- Current and Previous are Empty. + + function Is_Transient_Action (N : Node_Id) return Boolean; + -- Returns True for nodes that belong to a transient action and so they + -- have no parent, because they have not been inserted to the tree yet. + + ------------------------------- + -- Find_In_Enclosing_Context -- + ------------------------------- + + procedure Find_In_Enclosing_Context + (Stmt : Node_Id; Current, Previous : in out Node_Id) + is + begin + loop + -- If we fall off the top of the tree, then that's odd, but + -- perhaps it could occur in some error situation, and the safest + -- response is simply to assume that the outcome of the condition + -- is unknown. No point in bombing during an attempt to optimize + -- things. + + if No (Current) then + + -- In particular, we expect to miss the enclosing conditional + -- statement for: + -- * references within a freezing action (because their + -- location is unrelated to the conditional statement), + -- * validity checks (becuase for references inside the + -- condition they are inserted before the conditional + -- statement itself), + -- * source locations before and after the conditionaal + -- statement. + + pragma Assert + (Inside_Freezing_Actions > 0 + or else + (Ekind (Entity (Var)) = E_Variable + and then Present (Validated_Object (Entity (Var)))) + or else + Loc < Sloc (Stmt) + or else + Loc >= Sloc (Stmt) + Text_Ptr (UI_To_Int (End_Span (Stmt))) + or else + Serious_Errors_Detected > 0); + + return; + + -- We found the enclosing conditional statement + + elsif Current = Stmt then + return; + + -- For itype declarations follow their associated node + + elsif Nkind (Current) = N_Subtype_Declaration + and then Is_Itype (Defining_Identifier (Current)) + then + Previous := Current; + Current := + Associated_Node_For_Itype (Defining_Identifier (Previous)); + + -- If associated node has not been set yet, we can use the + -- related expression, which is set earlier. + -- ??? this should be investigated + + if No (Current) then + Current := + Related_Expression (Defining_Identifier (Previous)); + end if; + pragma Assert (Present (Current)); + + -- Same for itypes that have no declaration + + elsif Nkind (Current) = N_Defining_Identifier + and then Is_Itype (Current) + then + pragma Assert (No (Parent (Current))); + Previous := Current; + Current := Associated_Node_For_Itype (Previous); + + -- For transient actions follow where they will be inserted + + elsif Is_Transient_Action (Current) then + Previous := Current; + Current := + Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped; + + -- Otherwise, continue climbing + + else + Previous := Current; + Current := Parent (Current); + end if; + end loop; + end Find_In_Enclosing_Context; + + ------------------------- + -- Is_Transient_Action -- + ------------------------- + + function Is_Transient_Action (N : Node_Id) return Boolean is + begin + if Scope_Stack.Last >= Scope_Stack.First + and then Scope_Is_Transient + and then Is_List_Member (N) + then + declare + Transient_Actions : Scope_Actions renames + Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped; + begin + for Action_Kind in Scope_Actions'Range loop + if List_Containing (N) = Transient_Actions (Action_Kind) then + return True; + end if; + end loop; + end; + end if; + + return False; + end Is_Transient_Action; + procedure Process_Current_Value_Condition (N : Node_Id; S : Boolean); -- N is an expression which holds either True (S = True) or False (S = -- False) in the condition. This procedure digs out the expression and @@ -7490,156 +7618,71 @@ package body Exp_Util is declare CV : constant Node_Id := Current_Value (Ent); Sens : Boolean; - Stm : Node_Id; begin - -- If statement. Condition is known true in THEN section, known False - -- in any ELSIF or ELSE part, and unknown outside the IF statement. - - if Nkind (CV) = N_If_Statement then + -- For IF statement the condition is known true in THEN section, + -- known False in any ELSIF or ELSE part, and unknown outside the + -- IF statement. - -- Before start of IF statement - - if Loc < Sloc (CV) then - return; - - -- In condition of IF statement - - elsif In_Subtree (N => Var, Root => Condition (CV)) then - return; + if Nkind (CV) in N_If_Statement | N_Elsif_Part then - -- After end of IF statement - - elsif Loc >= Sloc (CV) + Text_Ptr (UI_To_Int (End_Span (CV))) then - return; - end if; - - -- At this stage we know that we are within the IF statement, but - -- unfortunately, the tree does not record the SLOC of the ELSE so - -- we cannot use a simple SLOC comparison to distinguish between - -- the then/else statements, so we have to climb the tree. + -- At this stage we know that we are within the conditional + -- statement, but we have to climb the tree to know in which + -- part, e.g. in THEN or ELSE statements of an IF statement. declare - N : Node_Id; - - begin - N := Parent (Var); - while Parent (N) /= CV loop - N := Parent (N); + If_Stmt : constant Node_Id := + (if Nkind (CV) = N_If_Statement + then CV + else Parent (CV)); - -- If we fall off the top of the tree, then that's odd, but - -- perhaps it could occur in some error situation, and the - -- safest response is simply to assume that the outcome of - -- the condition is unknown. No point in bombing during an - -- attempt to optimize things. + Previous : Node_Id := Var; + Current : Node_Id := Parent (Var); - if No (N) then - return; - end if; - end loop; - - -- Now we have N pointing to a node whose parent is the IF - -- statement in question, so now we can tell if we are within - -- the THEN statements. - - if Is_List_Member (N) - and then List_Containing (N) = Then_Statements (CV) - then - Sens := True; - - -- If the variable reference does not come from source, we - -- cannot reliably tell whether it appears in the else part. - -- In particular, if it appears in generated code for a node - -- that requires finalization, it may be attached to a list - -- that has not been yet inserted into the code. For now, - -- treat it as unknown. + begin + -- An ELSIF part whose condition is false could have been + -- already rewritten into NULL statement and we are already + -- past the statements inside that ELSIF part. - elsif not Comes_From_Source (N) then + if Nkind (If_Stmt) /= N_If_Statement then + pragma Assert + (Nkind (CV) = N_Elsif_Part + and then Is_Rewrite_Substitution (If_Stmt)); return; - - -- Otherwise we must be in ELSIF or ELSE part - - else - Sens := False; end if; - end; - -- ELSIF part. Condition is known true within the referenced - -- ELSIF, known False in any subsequent ELSIF or ELSE part, - -- and unknown before the ELSE part or after the IF statement. - - elsif Nkind (CV) = N_Elsif_Part then - - -- if the Elsif_Part had condition_actions, the elsif has been - -- rewritten as a nested if, and the original elsif_part is - -- detached from the tree, so there is no way to obtain useful - -- information on the current value of the variable. - -- Can this be improved ??? - - if No (Parent (CV)) then - return; - end if; - - Stm := Parent (CV); - - -- If the tree has been otherwise rewritten there is nothing - -- else to be done either. - - if Nkind (Stm) /= N_If_Statement then - return; - end if; - - -- Before start of ELSIF part - - if Loc < Sloc (CV) then - return; + Find_In_Enclosing_Context (If_Stmt, Current, Previous); - -- In condition of ELSIF part - - elsif In_Subtree (N => Var, Root => Condition (CV)) then - return; - - -- After end of IF statement + -- Check whether the reference is in the IF, THEN or ELSE/ELSIF + -- part. - elsif Loc >= Sloc (Stm) + - Text_Ptr (UI_To_Int (End_Span (Stm))) - then - return; - end if; + if Current = If_Stmt then - -- Again we lack the SLOC of the ELSE, so we need to climb the - -- tree to see if we are within the ELSIF part in question. + -- Ignore references from within the IF condition itself - declare - N : Node_Id; + if Previous = Condition (If_Stmt) then + return; - begin - N := Parent (Var); - while Parent (N) /= Stm loop - N := Parent (N); + -- Guard against if-statements coming from if-statements + -- with broken chain of parents. - -- If we fall off the top of the tree, then that's odd, but - -- perhaps it could occur in some error situation, and the - -- safest response is simply to assume that the outcome of - -- the condition is unknown. No point in bombing during an - -- attempt to optimize things. + elsif Is_List_Member (Previous) then + pragma Assert ( + List_Containing (Previous) + in Then_Statements (If_Stmt) + | Elsif_Parts (If_Stmt) + | Else_Statements (If_Stmt)); - if No (N) then + Sens := + (if CV = If_Stmt + then List_Containing (Previous) = Then_Statements (CV) + else Previous = CV); + else + pragma Assert (From_Conditional_Expression (If_Stmt)); return; end if; - end loop; - - -- Now we have N pointing to a node whose parent is the IF - -- statement in question, so see if is the ELSIF part we want. - -- the THEN statements. - - if N = CV then - Sens := True; - - -- Otherwise we must be in subsequent ELSIF or ELSE part - else - Sens := False; + return; end if; end; @@ -7650,26 +7693,31 @@ package body Exp_Util is declare Loop_Stmt : constant Node_Id := Parent (CV); + Previous : Node_Id := Var; + Current : Node_Id := Parent (Var); + begin - -- Before start of body of loop + pragma Assert (Nkind (Loop_Stmt) = N_Loop_Statement); - if Loc < Sloc (Loop_Stmt) then - return; + Find_In_Enclosing_Context (Loop_Stmt, Current, Previous); - -- In condition of while loop + -- Check whether the reference is inside the WHILE loop - elsif In_Subtree (N => Var, Root => Condition (CV)) then - return; + if Current = Loop_Stmt then - -- After end of LOOP statement + -- Ignore references from within the WHILE condition itself - elsif Loc >= Sloc (End_Label (Loop_Stmt)) then - return; + if Previous = Iteration_Scheme (Loop_Stmt) then + return; - -- We are within the body of the loop + else + pragma Assert + (List_Containing (Previous) = Statements (Loop_Stmt)); + Sens := True; + end if; else - Sens := True; + return; end if; end; diff --git a/gcc/ada/fname.adb b/gcc/ada/fname.adb index 6022d3b..c914c55 100644 --- a/gcc/ada/fname.adb +++ b/gcc/ada/fname.adb @@ -134,19 +134,6 @@ package body Fname is Renamings_Included : Boolean := True) return Boolean is begin - -- Definitely false if longer than 12 characters (8.3), except for the - -- Interfaces packages and also the implementation units of the 128-bit - -- types under System. - - if Fname'Length > 12 - and then Fname (Fname'First .. Fname'First + 1) /= "i-" - and then Fname (Fname'First .. Fname'First + 1) /= "s-" - and then not Has_Prefix (Fname, "system-") - and then not Has_Prefix (Fname, "interfac__") - then - return False; - end if; - if not Has_Internal_Extension (Fname) then return False; end if; diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index d8fdc30..66145e5 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -8382,7 +8382,8 @@ package body Freeze is -- and Per-Object Expressions" will suppress the insertion, and the -- freeze node will be dropped on the floor. - if Saved_Ghost_Config.Ghost_Mode = Ignore + if not CodePeer_Mode + and then Saved_Ghost_Config.Ghost_Mode = Ignore and then Ghost_Config.Ghost_Mode /= Ignore and then Present (Ghost_Config.Ignored_Ghost_Region) then diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads index 6cd1355..d25006c 100644 --- a/gcc/ada/gen_il-fields.ads +++ b/gcc/ada/gen_il-fields.ads @@ -131,7 +131,6 @@ package Gen_IL.Fields is Corresponding_Stub, Dcheck_Function, Declarations, - Default_Expression, Default_Storage_Pool, Default_Name, Default_Subtype_Mark, @@ -153,7 +152,6 @@ package Gen_IL.Fields is Do_Length_Check, Do_Overflow_Check, Do_Range_Check, - Do_Storage_Check, Elaborate_All_Desirable, Elaborate_All_Present, Elaborate_Desirable, @@ -161,7 +159,6 @@ package Gen_IL.Fields is Else_Actions, Else_Statements, Elsif_Parts, - Enclosing_Variant, End_Label, End_Span, Entity_Or_Associated_Node, @@ -204,7 +201,6 @@ package Gen_IL.Fields is Generic_Parent, Generic_Parent_Type, Handled_Statement_Sequence, - Handler_List_Entry, Has_Created_Identifier, Has_Dereference_Action, Has_Dynamic_Length_Check, @@ -283,7 +279,6 @@ package Gen_IL.Fields is Is_Static_Coextension, Is_Static_Expression, Is_Structural, - Is_Subprogram_Descriptor, Is_Task_Allocation_Block, Is_Task_Body_Procedure, Is_Task_Master, @@ -376,7 +371,6 @@ package Gen_IL.Fields is Reason, Record_Extension_Part, Redundant_Use, - Renaming_Exception, Result_Definition, Return_Object_Declarations, Return_Statement_Entity, @@ -480,8 +474,6 @@ package Gen_IL.Fields is Component_Clause, Component_Size, Component_Type, - Constructor_List, - Constructor_Name, Continue_Mark, Contract, Contract_Wrapper, @@ -614,7 +606,6 @@ package Gen_IL.Fields is Has_Own_Invariants, Has_Partial_Visible_Refinement, Has_Per_Object_Constraint, - Has_Pragma_Controlled, Has_Pragma_Elaborate_Body, Has_Pragma_Inline, Has_Pragma_Inline_Always, @@ -808,7 +799,6 @@ package Gen_IL.Fields is Is_Unchecked_Union, Is_Underlying_Full_View, Is_Underlying_Record_View, - Is_Unimplemented, Is_Unsigned_Type, Is_Uplevel_Referenced_Entity, Is_Valued_Procedure, @@ -818,6 +808,7 @@ package Gen_IL.Fields is Is_Volatile_Object, Is_Volatile_Full_Access, Is_Wrapper, + Is_IEEE_Extended_Precision, Itype_Printed, Kill_Elaboration_Checks, Known_To_Have_Preelab_Init, diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb index bd091cb..d3ac63a 100644 --- a/gcc/ada/gen_il-gen-gen_entities.adb +++ b/gcc/ada/gen_il-gen-gen_entities.adb @@ -203,7 +203,6 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Is_Unchecked_Union, Flag, Impl_Base_Type_Only), Sm (Is_Underlying_Full_View, Flag), Sm (Is_Underlying_Record_View, Flag, Base_Type_Only), - Sm (Is_Unimplemented, Flag), Sm (Is_Uplevel_Referenced_Entity, Flag), Sm (Is_Visible_Formal, Flag), Sm (Is_Visible_Lib_Unit, Flag), @@ -456,8 +455,6 @@ begin -- Gen_IL.Gen.Gen_Entities Pre => "Ekind (Base_Type (N)) in Access_Subprogram_Kind"), Sm (Class_Wide_Equivalent_Type, Node_Id), Sm (Class_Wide_Type, Node_Id), - Sm (Constructor_List, Elist_Id), - Sm (Constructor_Name, Node_Id), Sm (Contract, Node_Id), Sm (Current_Use_Clause, Node_Id), Sm (Derived_Type_Link, Node_Id), @@ -630,7 +627,8 @@ begin -- Gen_IL.Gen.Gen_Entities -- first named subtype). Ab (Float_Kind, Real_Kind, - (Sm (Digits_Value, Upos))); + (Sm (Digits_Value, Upos), + Sm (Is_IEEE_Extended_Precision, Flag))); Cc (E_Floating_Point_Type, Float_Kind); -- Floating point type, used for the anonymous base type of the @@ -646,7 +644,6 @@ begin -- Gen_IL.Gen.Gen_Entities (Sm (Associated_Storage_Pool, Node_Id, Root_Type_Only), Sm (Directly_Designated_Type, Node_Id), Sm (Finalization_Collection, Node_Id, Root_Type_Only), - Sm (Has_Pragma_Controlled, Flag, Impl_Base_Type_Only), Sm (Has_Storage_Size_Clause, Flag, Impl_Base_Type_Only), Sm (Is_Access_Constant, Flag), Sm (Is_Local_Anonymous_Access, Flag), diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb index 9ce2511..e6e00ff 100644 --- a/gcc/ada/gen_il-gen-gen_nodes.adb +++ b/gcc/ada/gen_il-gen-gen_nodes.adb @@ -192,14 +192,24 @@ begin -- Gen_IL.Gen.Gen_Nodes (Sy (Char_Literal_Value, Unat))); Ab (N_Op, N_Has_Entity, - (Sm (Chars, Name_Id), - Sm (Do_Overflow_Check, Flag), + (Sm (Do_Overflow_Check, Flag), Sm (Has_Private_View, Flag), Sm (Has_Secondary_Private_View, Flag))); Ab (N_Binary_Op, N_Op, (Sy (Left_Opnd, Node_Id), - Sy (Right_Opnd, Node_Id))); + Sy (Right_Opnd, Node_Id), + Sy (Chars, Name_Id, Default_No_Name))); + -- N_Binary_Op and N_Unary_Op do not strictly need Chars, since the value + -- is fully determined by the Nkind. However, for example, Errout refers to + -- Chars without knowing statically whether the Nkind is in N_Op. + -- In any case, we don't inherit Chars from N_Op, because we want it to + -- come after the other syntactic fields, so that positional notation can + -- be used in calls to Make_Op_Add and friends. + -- + -- Make_Op_Add and friends will now have a Chars parameter. Callers + -- should always use the default, because the Chars field is set + -- properly as a special case (see Gen_IL.Gen). Cc (N_Op_Add, N_Binary_Op); @@ -259,7 +269,8 @@ begin -- Gen_IL.Gen.Gen_Nodes Cc (N_Op_Shift_Right_Arithmetic, N_Op_Shift); Ab (N_Unary_Op, N_Op, - (Sy (Right_Opnd, Node_Id))); + (Sy (Right_Opnd, Node_Id), + Sy (Chars, Name_Id, Default_No_Name))); Cc (N_Op_Abs, N_Unary_Op); Cc (N_Op_Minus, N_Unary_Op); @@ -290,7 +301,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Ab (N_Short_Circuit, N_Subexpr, (Sy (Left_Opnd, Node_Id), Sy (Right_Opnd, Node_Id), - Sm (Actions, List_Id))); + Sy (Actions, List_Id, Default_No_List))); Cc (N_And_Then, N_Short_Circuit); Cc (N_Or_Else, N_Short_Circuit); @@ -403,7 +414,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sy (Null_Exclusion_Present, Flag, Default_False), Sy (Expression, Node_Id, Default_Empty), Sm (For_Special_Return_Object, Flag), - Sm (Do_Storage_Check, Flag), Sm (Is_Dynamic_Coextension, Flag), Sm (Is_Static_Coextension, Flag), Sm (No_Initialization, Flag), @@ -515,7 +525,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Sy (Null_Exclusion_Present, Flag, Default_False), Sy (Access_Definition, Node_Id, Default_Empty), Sy (Subtype_Mark, Node_Id, Default_Empty), - Sy (Default_Expression, Node_Id, Default_Empty), + Sy (Expression, Node_Id, Default_Empty), Sy (Aspect_Specifications, List_Id, Default_No_List), Sm (More_Ids, Flag), Sm (Prev_Ids, Flag))); @@ -568,8 +578,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Assignment_OK, Flag), Sm (Corresponding_Generic_Association, Node_Id), Sm (Exception_Junk, Flag), - Sm (Handler_List_Entry, Node_Id), - Sm (Is_Subprogram_Descriptor, Flag), Sm (More_Ids, Flag), Sm (No_Initialization, Flag), Sm (Prev_Ids, Flag), @@ -730,7 +738,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Activation_Chain_Entity, Node_Id), Sm (Acts_As_Spec, Flag), Sm (Corresponding_Entry_Body, Node_Id), - Sm (Do_Storage_Check, Flag), Sm (Has_Relative_Deadline_Pragma, Flag), Sm (Is_Entry_Barrier_Function, Flag), Sm (Is_Protected_Subprogram_Body, Flag), @@ -1154,9 +1161,9 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Target, Node_Id))); Cc (N_Case_Expression_Alternative, Node_Kind, - (Sm (Actions, List_Id), - Sy (Discrete_Choices, List_Id), + (Sy (Discrete_Choices, List_Id), Sy (Expression, Node_Id, Default_Empty), + Sy (Actions, List_Id, Default_No_List), Sm (Has_SP_Choice, Flag))); Cc (N_Case_Statement_Alternative, Node_Kind, @@ -1283,10 +1290,9 @@ begin -- Gen_IL.Gen.Gen_Nodes Cc (N_Exception_Declaration, N_Declaration, (Sy (Defining_Identifier, Node_Id), Sy (Aspect_Specifications, List_Id, Default_No_List), - Sm (Expression, Node_Id), + Sy (Expression, Node_Id, Default_Empty), Sm (More_Ids, Flag), - Sm (Prev_Ids, Flag), - Sm (Renaming_Exception, Node_Id))); + Sm (Prev_Ids, Flag))); Cc (N_Exception_Handler, Node_Kind, (Sy (Choice_Parameter, Node_Id, Default_Empty), @@ -1426,7 +1432,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sy (Parameter_Type, Node_Id), Sy (Expression, Node_Id, Default_Empty), Sy (Aspect_Specifications, List_Id, Default_No_List), - Sm (Default_Expression, Node_Id), Sm (More_Ids, Flag), Sm (Prev_Ids, Flag))); @@ -1531,7 +1536,6 @@ begin -- Gen_IL.Gen.Gen_Nodes (Sy (Discrete_Choices, List_Id), Sy (Component_List, Node_Id), Sm (Dcheck_Function, Node_Id), - Sm (Enclosing_Variant, Node_Id), Sm (Has_SP_Choice, Flag), Sm (Present_Expr, Uint))); diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb index 5eb1a58..873c3cd 100644 --- a/gcc/ada/gen_il-gen.adb +++ b/gcc/ada/gen_il-gen.adb @@ -167,7 +167,6 @@ package body Gen_IL.Gen is -- Check that syntactic fields precede semantic fields. Note that this -- check is happening before we compute inherited fields. - -- Exempt Chars and Actions from this rule, for now. declare Semantic_Seen : Boolean := False; @@ -178,11 +177,8 @@ package body Gen_IL.Gen is raise Illegal with "syntactic fields must precede semantic ones " & Image (T); end if; - else - if Fields (J).F not in Chars | Actions then - Semantic_Seen := True; - end if; + Semantic_Seen := True; end if; end loop; end; @@ -509,14 +505,11 @@ package body Gen_IL.Gen is Node_Field_Types_Used, Entity_Field_Types_Used : Type_Set; Setter_Needs_Parent : Field_Set := - (Actions | Expression | Then_Actions | Else_Actions => True, + (Then_Actions | Else_Actions => True, others => False); -- Set of fields where the setter should set the Parent. True for - -- syntactic fields of type Node_Id and List_Id, but with some - -- exceptions. Expression is syntactic AND semantic, and the Parent - -- is needed. Default_Expression is also both, but the Parent is not - -- needed. Then_Actions and Else_Actions are not syntactic, but the - -- Parent is needed. + -- syntactic fields of type Node_Id and List_Id. Then_Actions and + -- Else_Actions are not syntactic, but the Parent is needed. -- -- Computed in Check_For_Syntactic_Field_Mismatch. @@ -896,7 +889,7 @@ package body Gen_IL.Gen is -- For example, Left_Opnd comes before Right_Opnd, -- which wouldn't be the case if Right_Opnd were -- inherited from N_Op. - ((T = N_Op and then F = Right_Opnd) + ((T = N_Op and then F in Right_Opnd | Chars) or else (T = N_Renaming_Declaration and then F = Name) or else (T = N_Generic_Renaming_Declaration and then F = Name) or else F in Defining_Unit_Name @@ -1301,26 +1294,15 @@ package body Gen_IL.Gen is end if; end loop; - -- The following fields violate this rule. We might want to - -- simplify by getting rid of these cases, but we allow them - -- for now. At least, we don't want to add any new cases of - -- syntactic/semantic mismatch. + if Syntactic_Seen and Semantic_Seen then + raise Illegal with + "syntactic/semantic mismatch for " & Image (F); + end if; - if F in Chars | Actions | Expression | Default_Expression + if Field_Table (F).Field_Type in Traversed_Field_Type + and then Syntactic_Seen then - pragma Assert (Syntactic_Seen and Semantic_Seen); - - else - if Syntactic_Seen and Semantic_Seen then - raise Illegal with - "syntactic/semantic mismatch for " & Image (F); - end if; - - if Field_Table (F).Field_Type in Traversed_Field_Type - and then Syntactic_Seen - then - Setter_Needs_Parent (F) := True; - end if; + Setter_Needs_Parent (F) := True; end if; end; end if; @@ -2675,7 +2657,7 @@ package body Gen_IL.Gen is if Is_Descendant (N_Op, T) then -- Special cases for N_Op nodes: fill in the Chars and Entity - -- fields even though they were not passed in. + -- fields. Assert that the Chars passed in is defaulted. declare Op : constant String := Image_Sans_N (T); @@ -2705,6 +2687,7 @@ package body Gen_IL.Gen is -- "Op_", but the Name_Id constant does not. begin + Put (S, "pragma Assert (Chars = No_Name);" & LF); Put (S, "Set_Chars (N, Name_" & Op_Name & ");" & LF); Put (S, "Set_Entity (N, Standard_" & Op & ");" & LF); end; @@ -2990,7 +2973,7 @@ package body Gen_IL.Gen is (if T in Entity_Type and then F in Node_Field then " -- N" else ""); -- A comment to put out for fields of entities that are - -- shared with nodes, such as Chars. + -- shared with nodes. begin while First_Bit < Type_Bit_Size_Aligned (T) loop diff --git a/gcc/ada/gen_il-gen.ads b/gcc/ada/gen_il-gen.ads index cb364ad..149afe1 100644 --- a/gcc/ada/gen_il-gen.ads +++ b/gcc/ada/gen_il-gen.ads @@ -48,14 +48,12 @@ -- If a field is syntactic, then the constructors in Nmake take a parameter to -- initialize that field. In addition, the tree-traversal routines in Atree -- (Traverse_Func and Traverse_Proc) traverse syntactic fields that are of --- type Node_Id (or subtypes of Node_Id) or List_Id. Finally, (with some --- exceptions documented in the body) the setter for a syntactic node or list --- field "Set_F (N, Val)" will set the Parent of Val to N, unless Val is Empty --- or Error[_List]. +-- type Node_Id (or subtypes of Node_Id) or List_Id. Finally, the setter for a +-- syntactic node or list field "Set_F (N, Val)" will set the Parent of Val to +-- N, unless Val is Empty or Error[_List]. -- --- Note that the same field can be syntactic in some node types but semantic --- in other node types. This is an added complexity that we might want to --- eliminate someday. We shouldn't add any new such cases. +-- No syntactic/semantic mixing: the same field cannot be syntactic in some +-- node types but semantic in other node types. -- -- A "program" written in the Gen_IL.Gen language consists of calls to the -- "Create_..." routines below, followed by a call to Compile, also below. In diff --git a/gcc/ada/gen_il-internals.adb b/gcc/ada/gen_il-internals.adb index 77685f2..bd2d480 100644 --- a/gcc/ada/gen_il-internals.adb +++ b/gcc/ada/gen_il-internals.adb @@ -311,6 +311,8 @@ package body Gen_IL.Internals is return "Is_Elaboration_Warnings_OK_Id"; when Is_Elaboration_Warnings_OK_Node => return "Is_Elaboration_Warnings_OK_Node"; + when Is_IEEE_Extended_Precision => + return "Is_IEEE_Extended_Precision"; when Is_Known_Guaranteed_ABE => return "Is_Known_Guaranteed_ABE"; when Is_RACW_Stub_Type => diff --git a/gcc/ada/ghost.adb b/gcc/ada/ghost.adb index e7a55ef..d49d94d 100644 --- a/gcc/ada/ghost.adb +++ b/gcc/ada/ghost.adb @@ -740,6 +740,14 @@ package body Ghost is then return True; + -- It is always legal to use a ghost prefix. More complex + -- scenarios are analyzed for the selector. + + elsif Nkind (Par) = N_Selected_Component + and then Prefix (Par) = Prev + then + return True; + elsif Is_OK_Declaration (Par) then return True; diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 68a3c14..23c9977 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -19,7 +19,7 @@ @copying @quotation -GNAT Reference Manual , Oct 17, 2025 +GNAT Reference Manual , Oct 31, 2025 AdaCore @@ -20724,8 +20724,7 @@ machines with strict alignment requirements, GNAT checks (at compile time if possible, generating a warning, or at execution time with a run-time check) that the alignment is appropriate. If the run-time check fails, then @code{Program_Error} is raised. This run-time -check is suppressed if range checks are suppressed, or if the special GNAT -check Alignment_Check is suppressed, or if +check is suppressed if the GNAT check Alignment_Check is suppressed, or if @code{pragma Restrictions (No_Elaboration_Code)} is in effect. It is also suppressed by default on non-strict alignment machines (such as the x86). diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 86b2cbc..4789757 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -19,7 +19,7 @@ @copying @quotation -GNAT User's Guide for Native Platforms , Oct 06, 2025 +GNAT User's Guide for Native Platforms , Oct 31, 2025 AdaCore @@ -30333,8 +30333,8 @@ to permit their use in free software. @printindex ge -@anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ } @anchor{d2}@w{ } +@anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ } @c %**end of body @bye diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb index 9e60fa8..a966c28 100644 --- a/gcc/ada/inline.adb +++ b/gcc/ada/inline.adb @@ -3380,15 +3380,6 @@ package body Inline is -- be performed in a separate pass, using an instantiation of the -- previous subprogram over aspect specifications reachable from N. - function Process_Sloc (Nod : Node_Id) return Traverse_Result; - -- If the call being expanded is that of an internal subprogram, set the - -- sloc of the generated block to that of the call itself, so that the - -- expansion is skipped by the "next" command in gdb. Same processing - -- for a subprogram in a predefined file, e.g. Ada.Tags. If - -- Debug_Generated_Code is true, suppress this change to simplify our - -- own development. Same in GNATprove mode, to ensure that warnings and - -- diagnostics point to the proper location. - procedure Reset_Dispatching_Calls (N : Node_Id); -- In subtree N search for occurrences of dispatching calls that use the -- Ada 2005 Object.Operation notation and the object is a formal of the @@ -3647,22 +3638,6 @@ package body Inline is procedure Replace_Formals_In_Aspects is new Traverse_Proc (Process_Formals_In_Aspects); - ------------------ - -- Process_Sloc -- - ------------------ - - function Process_Sloc (Nod : Node_Id) return Traverse_Result is - begin - if not Debug_Generated_Code then - Set_Sloc (Nod, Sloc (N)); - Set_Comes_From_Source (Nod, False); - end if; - - return OK; - end Process_Sloc; - - procedure Reset_Slocs is new Traverse_Proc (Process_Sloc); - ------------------------------ -- Reset_Dispatching_Calls -- ------------------------------ @@ -4176,13 +4151,6 @@ package body Inline is Replace_Formals_In_Aspects (Blk); Set_Parent (Blk, N); - if GNATprove_Mode then - null; - - elsif not Comes_From_Source (Subp) or else Is_Predef then - Reset_Slocs (Blk); - end if; - if Is_Unc_Decl then -- No action needed since return statement has been already removed diff --git a/gcc/ada/libgnat/a-cbmutr.adb b/gcc/ada/libgnat/a-cbmutr.adb index 9d9d21d..bd6b135 100644 --- a/gcc/ada/libgnat/a-cbmutr.adb +++ b/gcc/ada/libgnat/a-cbmutr.adb @@ -2357,11 +2357,11 @@ is end Rec; begin - if First_Child (Root (V)) = No_Element then + if Is_Empty (V) then Array_Before (S); Array_After (S); else - Rec (First_Child (Root (V))); + Rec (Root (V)); end if; end Put_Image; diff --git a/gcc/ada/libgnat/a-cimutr.adb b/gcc/ada/libgnat/a-cimutr.adb index b84eb16..0c6d338 100644 --- a/gcc/ada/libgnat/a-cimutr.adb +++ b/gcc/ada/libgnat/a-cimutr.adb @@ -1910,11 +1910,11 @@ is end Rec; begin - if First_Child (Root (V)) = No_Element then + if Is_Empty (V) then Array_Before (S); Array_After (S); else - Rec (First_Child (Root (V))); + Rec (Root (V)); end if; end Put_Image; diff --git a/gcc/ada/libgnat/a-comutr.adb b/gcc/ada/libgnat/a-comutr.adb index df3741b..2d6393d 100644 --- a/gcc/ada/libgnat/a-comutr.adb +++ b/gcc/ada/libgnat/a-comutr.adb @@ -1844,11 +1844,11 @@ is end Rec; begin - if First_Child (Root (V)) = No_Element then + if Is_Empty (V) then Array_Before (S); Array_After (S); else - Rec (First_Child (Root (V))); + Rec (Root (V)); end if; end Put_Image; diff --git a/gcc/ada/libgnat/s-dwalin.adb b/gcc/ada/libgnat/s-dwalin.adb index 1e97a47..713aad4 100644 --- a/gcc/ada/libgnat/s-dwalin.adb +++ b/gcc/ada/libgnat/s-dwalin.adb @@ -1912,11 +1912,12 @@ package body System.Dwarf_Lines is ------------------------ procedure Symbolic_Traceback - (Cin : Dwarf_Context; - Traceback : STE.Tracebacks_Array; - Suppress_Hex : Boolean; - Symbol_Found : out Boolean; - Res : in out System.Bounded_Strings.Bounded_String) + (Cin : Dwarf_Context; + Traceback : STE.Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Symbol_Found : out Boolean; + Res : in out System.Bounded_Strings.Bounded_String) is use Ada.Characters.Handling; C : Dwarf_Context := Cin; @@ -1953,7 +1954,7 @@ package body System.Dwarf_Lines is -- If we're not requested to suppress hex addresses, emit it now. - if not Suppress_Hex then + if not Suppress_Hex and then not Subprg_Name_Only then Append_Address (Res, Addr_In_Traceback); Append (Res, ' '); end if; @@ -2006,10 +2007,12 @@ package body System.Dwarf_Lines is Append (Res, "???"); end if; - Append (Res, " at "); - Append (Res, String (File_Name (1 .. Last))); - Append (Res, ':'); - Append (Res, Line_Image (2 .. Line_Image'Last)); + if not Subprg_Name_Only then + Append (Res, " at "); + Append (Res, String (File_Name (1 .. Last))); + Append (Res, ':'); + Append (Res, Line_Image (2 .. Line_Image'Last)); + end if; end; else if Subprg_Name.Len > 0 then @@ -2020,7 +2023,9 @@ package body System.Dwarf_Lines is Append (Res, "???"); end if; - Append (Res, " at ???"); + if not Subprg_Name_Only then + Append (Res, " at ???"); + end if; end if; Append (Res, ASCII.LF); diff --git a/gcc/ada/libgnat/s-dwalin.ads b/gcc/ada/libgnat/s-dwalin.ads index c65d66e..641e515 100644 --- a/gcc/ada/libgnat/s-dwalin.ads +++ b/gcc/ada/libgnat/s-dwalin.ads @@ -80,11 +80,12 @@ package System.Dwarf_Lines is -- Read symbol information to speed up Symbolic_Traceback. procedure Symbolic_Traceback - (Cin : Dwarf_Context; - Traceback : STE.Tracebacks_Array; - Suppress_Hex : Boolean; - Symbol_Found : out Boolean; - Res : in out System.Bounded_Strings.Bounded_String); + (Cin : Dwarf_Context; + Traceback : STE.Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Symbol_Found : out Boolean; + Res : in out System.Bounded_Strings.Bounded_String); -- Generate a string for a traceback suitable for displaying to the user. -- If one or more symbols are found, Symbol_Found is set to True. This -- allows the caller to fall back to hexadecimal addresses. diff --git a/gcc/ada/libgnat/s-stratt.adb b/gcc/ada/libgnat/s-stratt.adb index 844c530..9315ae1 100644 --- a/gcc/ada/libgnat/s-stratt.adb +++ b/gcc/ada/libgnat/s-stratt.adb @@ -1036,4 +1036,21 @@ package body System.Stream_Attributes is Ada.Streams.Write (Stream.all, From_WWC (Item)); end W_WWC; + procedure W_80IEEE (Stream : not null access RST; Item : Long_Long_Float) is + begin + if XDR_Support then + XDR.W_LLF (Stream, Item); + return; + end if; + + declare + X : S_LLF := From_LLF (Item); + + N_IEEE_Extended_Precision_Bytes : constant := 10; + begin + X (N_IEEE_Extended_Precision_Bytes + 1 .. X'Last) := (others => 0); + Ada.Streams.Write (Stream.all, X); + end; + end W_80IEEE; + end System.Stream_Attributes; diff --git a/gcc/ada/libgnat/s-stratt.ads b/gcc/ada/libgnat/s-stratt.ads index 87f1357..9f27f5a 100644 --- a/gcc/ada/libgnat/s-stratt.ads +++ b/gcc/ada/libgnat/s-stratt.ads @@ -171,6 +171,8 @@ package System.Stream_Attributes is procedure W_WC (Stream : not null access RST; Item : Wide_Character); procedure W_WWC (Stream : not null access RST; Item : Wide_Wide_Character); + procedure W_80IEEE (Stream : not null access RST; Item : Long_Long_Float); + function Block_IO_OK return Boolean; -- Indicate whether the current setting supports block IO. See -- System.Strings.Stream_Ops (s-ststop) for details on block IO. diff --git a/gcc/ada/libgnat/s-stratt__cheri.adb b/gcc/ada/libgnat/s-stratt__cheri.adb index aefb8b3..9e336f3 100644 --- a/gcc/ada/libgnat/s-stratt__cheri.adb +++ b/gcc/ada/libgnat/s-stratt__cheri.adb @@ -1016,4 +1016,21 @@ package body System.Stream_Attributes is Ada.Streams.Write (Stream.all, From_WWC (Item)); end W_WWC; + procedure W_80IEEE (Stream : not null access RST; Item : Long_Long_Float) is + begin + if XDR_Support then + XDR.W_LLF (Stream, Item); + return; + end if; + + declare + X : S_LLF := From_LLF (Item); + + N_IEEE_Extended_Precision_Bytes : constant := 10; + begin + X (N_IEEE_Extended_Precision_Bytes + 1 .. X'Last) := (others => 0); + Ada.Streams.Write (Stream.all, X); + end; + end W_80IEEE; + end System.Stream_Attributes; diff --git a/gcc/ada/libgnat/s-trasym.adb b/gcc/ada/libgnat/s-trasym.adb index 96a1925..5bab088 100644 --- a/gcc/ada/libgnat/s-trasym.adb +++ b/gcc/ada/libgnat/s-trasym.adb @@ -123,4 +123,8 @@ package body System.Traceback.Symbolic is null; end Enable_Cache; + function Calling_Entity return String is + begin + return "???"; + end Calling_Entity; end System.Traceback.Symbolic; diff --git a/gcc/ada/libgnat/s-trasym.ads b/gcc/ada/libgnat/s-trasym.ads index 96b26cb..59939ce 100644 --- a/gcc/ada/libgnat/s-trasym.ads +++ b/gcc/ada/libgnat/s-trasym.ads @@ -105,4 +105,7 @@ package System.Traceback.Symbolic is -- with default value), but backward compatibility for direct calls -- is supported. + function Calling_Entity return String; + -- Return the name of the caller of the current subprogram if it's + -- available. Otherwise return "???". end System.Traceback.Symbolic; diff --git a/gcc/ada/libgnat/s-trasym__dwarf.adb b/gcc/ada/libgnat/s-trasym__dwarf.adb index 479b5d3..09026c9 100644 --- a/gcc/ada/libgnat/s-trasym__dwarf.adb +++ b/gcc/ada/libgnat/s-trasym__dwarf.adb @@ -96,13 +96,16 @@ package body System.Traceback.Symbolic is -- Initialize Exec_Module if not already initialized function Symbolic_Traceback - (Traceback : System.Traceback_Entries.Tracebacks_Array; - Suppress_Hex : Boolean) return String; + (Traceback : System.Traceback_Entries.Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean) return String; function Symbolic_Traceback (E : Ada.Exceptions.Exception_Occurrence; Suppress_Hex : Boolean) return String; -- Suppress_Hex means do not print any hexadecimal addresses, even if the - -- symbol is not available. + -- symbol is not available. Subprg_Name_Only means to only print the + -- subprogram name for each frame, as opposed to the complete description + -- of the frame. function Lt (Left, Right : Module_Cache_Acc) return Boolean; -- Sort function for Module_Cache @@ -166,30 +169,34 @@ package body System.Traceback.Symbolic is -- Non-symbolic traceback (simply write addresses in hexa) procedure Symbolic_Traceback_No_Lock - (Traceback : Tracebacks_Array; - Suppress_Hex : Boolean; - Res : in out Bounded_String); - -- Like the public Symbolic_Traceback_No_Lock except there is no provision - -- against concurrent accesses. + (Traceback : Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String); + -- Like the public Symbolic_Traceback except there is no provision against + -- concurrent accesses. procedure Module_Symbolic_Traceback - (Traceback : Tracebacks_Array; - Module : Module_Cache; - Suppress_Hex : Boolean; - Res : in out Bounded_String); + (Traceback : Tracebacks_Array; + Module : Module_Cache; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String); -- Returns the Traceback for a given module procedure Multi_Module_Symbolic_Traceback - (Traceback : Tracebacks_Array; - Suppress_Hex : Boolean; - Res : in out Bounded_String); + (Traceback : Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String); -- Build string containing symbolic traceback for the given call chain procedure Multi_Module_Symbolic_Traceback - (Traceback : Tracebacks_Array; - Module : Module_Cache; - Suppress_Hex : Boolean; - Res : in out Bounded_String); + (Traceback : Tracebacks_Array; + Module : Module_Cache; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String); -- Likewise but using Module Max_String_Length : constant := 4096; @@ -328,6 +335,36 @@ package body System.Traceback.Symbolic is Module_Cache_Array_Sort (Modules_Cache.all); end Enable_Cache; + function Calling_Entity return String is + N_Skipped_Frames : constant Natural := 3; + -- We ask Call_Chain to skip the following frames: + -- + -- 1. The frame of Call_Chain itself. + -- 2. The frame of Calling_Entity. + -- 3. The frame of Calling_Entity's caller. + -- + -- The frame above that is the function the caller is looking for. + + Traceback : Tracebacks_Array (1 .. 1); + Len : Natural; + begin + Call_Chain (Traceback, 1, Len, Skip_Frames => N_Skipped_Frames); + + if Len = 0 then + return "???"; + end if; + + declare + With_Trailing_Newline : constant String := + Symbolic_Traceback + (Traceback, Suppress_Hex => True, Subprg_Name_Only => True); + begin + return + With_Trailing_Newline + (With_Trailing_Newline'First .. With_Trailing_Newline'Last - 1); + end; + end Calling_Entity; + --------------------- -- Executable_Name -- --------------------- @@ -450,14 +487,15 @@ package body System.Traceback.Symbolic is ------------------------------- procedure Module_Symbolic_Traceback - (Traceback : Tracebacks_Array; - Module : Module_Cache; - Suppress_Hex : Boolean; - Res : in out Bounded_String) + (Traceback : Tracebacks_Array; + Module : Module_Cache; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String) is Success : Boolean; begin - if Symbolic.Module_Name.Is_Supported then + if Symbolic.Module_Name.Is_Supported and then not Subprg_Name_Only then Append (Res, '['); Append (Res, Module.Name.all); Append (Res, ']' & ASCII.LF); @@ -467,11 +505,13 @@ package body System.Traceback.Symbolic is (Module.C, Traceback, Suppress_Hex, + Subprg_Name_Only, Success, Res); if not Success then - Hexa_Traceback (Traceback, Suppress_Hex, Res); + Hexa_Traceback + (Traceback, Suppress_Hex or else Subprg_Name_Only, Res); end if; -- We must not allow an unhandled exception here, since this function @@ -487,9 +527,10 @@ package body System.Traceback.Symbolic is ------------------------------------- procedure Multi_Module_Symbolic_Traceback - (Traceback : Tracebacks_Array; - Suppress_Hex : Boolean; - Res : in out Bounded_String) + (Traceback : Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String) is F : constant Natural := Traceback'First; begin @@ -514,6 +555,7 @@ package body System.Traceback.Symbolic is Multi_Module_Symbolic_Traceback (Traceback, Modules_Cache (Mid).all, + Subprg_Name_Only, Suppress_Hex, Res); return; @@ -527,6 +569,7 @@ package body System.Traceback.Symbolic is Multi_Module_Symbolic_Traceback (Traceback (F + 1 .. Traceback'Last), Suppress_Hex, + Subprg_Name_Only, Res); end; else @@ -534,10 +577,7 @@ package body System.Traceback.Symbolic is -- First try the executable if Is_Inside (Exec_Module.C, Traceback (F)) then Multi_Module_Symbolic_Traceback - (Traceback, - Exec_Module, - Suppress_Hex, - Res); + (Traceback, Exec_Module, Suppress_Hex, Subprg_Name_Only, Res); return; end if; @@ -553,10 +593,7 @@ package body System.Traceback.Symbolic is Init_Module (Module, Success, M_Name, Load_Addr); if Success then Multi_Module_Symbolic_Traceback - (Traceback, - Module, - Suppress_Hex, - Res); + (Traceback, Module, Suppress_Hex, Subprg_Name_Only, Res); Close_Module (Module); else -- Module not found @@ -564,6 +601,7 @@ package body System.Traceback.Symbolic is Multi_Module_Symbolic_Traceback (Traceback (F + 1 .. Traceback'Last), Suppress_Hex, + Subprg_Name_Only, Res); end if; end; @@ -571,10 +609,11 @@ package body System.Traceback.Symbolic is end Multi_Module_Symbolic_Traceback; procedure Multi_Module_Symbolic_Traceback - (Traceback : Tracebacks_Array; - Module : Module_Cache; - Suppress_Hex : Boolean; - Res : in out Bounded_String) + (Traceback : Tracebacks_Array; + Module : Module_Cache; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String) is Pos : Positive; begin @@ -599,10 +638,12 @@ package body System.Traceback.Symbolic is (Traceback (Traceback'First .. Pos - 1), Module, Suppress_Hex, + Subprg_Name_Only, Res); Multi_Module_Symbolic_Traceback (Traceback (Pos .. Traceback'Last), Suppress_Hex, + Subprg_Name_Only, Res); end Multi_Module_Symbolic_Traceback; @@ -633,23 +674,22 @@ package body System.Traceback.Symbolic is -------------------------------- procedure Symbolic_Traceback_No_Lock - (Traceback : Tracebacks_Array; - Suppress_Hex : Boolean; - Res : in out Bounded_String) - is + (Traceback : Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean; + Res : in out Bounded_String) is begin if Symbolic.Module_Name.Is_Supported then - Multi_Module_Symbolic_Traceback (Traceback, Suppress_Hex, Res); + Multi_Module_Symbolic_Traceback + (Traceback, Suppress_Hex, Subprg_Name_Only, Res); else if Exec_Module_State = Failed then Append (Res, "Call stack traceback locations:" & ASCII.LF); - Hexa_Traceback (Traceback, Suppress_Hex, Res); + Hexa_Traceback + (Traceback, Suppress_Hex or else Subprg_Name_Only, Res); else Module_Symbolic_Traceback - (Traceback, - Exec_Module, - Suppress_Hex, - Res); + (Traceback, Exec_Module, Suppress_Hex, Subprg_Name_Only, Res); end if; end if; end Symbolic_Traceback_No_Lock; @@ -662,8 +702,9 @@ package body System.Traceback.Symbolic is -- Copied from Ada.Exceptions.Exception_Data function Symbolic_Traceback - (Traceback : Tracebacks_Array; - Suppress_Hex : Boolean) return String + (Traceback : Tracebacks_Array; + Suppress_Hex : Boolean; + Subprg_Name_Only : Boolean) return String is Load_Address : constant Address := Get_Executable_Load_Address; Res : Bounded_String (Max_Length => Max_String_Length); @@ -671,12 +712,13 @@ package body System.Traceback.Symbolic is begin System.Soft_Links.Lock_Task.all; Init_Exec_Module; - if Load_Address /= Null_Address then + if not Subprg_Name_Only and then Load_Address /= Null_Address then Append (Res, LDAD_Header); Append_Address (Res, Load_Address); Append (Res, ASCII.LF); end if; - Symbolic_Traceback_No_Lock (Traceback, Suppress_Hex, Res); + Symbolic_Traceback_No_Lock + (Traceback, Suppress_Hex, Subprg_Name_Only, Res); System.Soft_Links.Unlock_Task.all; return To_String (Res); @@ -690,13 +732,17 @@ package body System.Traceback.Symbolic is function Symbolic_Traceback (Traceback : System.Traceback_Entries.Tracebacks_Array) return String is begin - return Symbolic_Traceback (Traceback, Suppress_Hex => False); + return + Symbolic_Traceback + (Traceback, Suppress_Hex => False, Subprg_Name_Only => False); end Symbolic_Traceback; function Symbolic_Traceback_No_Hex (Traceback : System.Traceback_Entries.Tracebacks_Array) return String is begin - return Symbolic_Traceback (Traceback, Suppress_Hex => True); + return + Symbolic_Traceback + (Traceback, Suppress_Hex => True, Subprg_Name_Only => False); end Symbolic_Traceback_No_Hex; function Symbolic_Traceback @@ -704,9 +750,11 @@ package body System.Traceback.Symbolic is Suppress_Hex : Boolean) return String is begin - return Symbolic_Traceback + return + Symbolic_Traceback (Ada.Exceptions.Traceback.Tracebacks (E), - Suppress_Hex); + Suppress_Hex, + False); end Symbolic_Traceback; function Symbolic_Traceback diff --git a/gcc/ada/par-ch12.adb b/gcc/ada/par-ch12.adb index 7bd449d..18cd907 100644 --- a/gcc/ada/par-ch12.adb +++ b/gcc/ada/par-ch12.adb @@ -466,7 +466,7 @@ package body Ch12 is end if; No_Constraint; - Set_Default_Expression (Decl_Node, Init_Expr_Opt); + Set_Expression (Decl_Node, Init_Expr_Opt); P_Aspect_Specifications (Decl_Node, Semicolon => True); if Ident > 1 then diff --git a/gcc/ada/par-ch13.adb b/gcc/ada/par-ch13.adb index dbb894f..00b780b 100644 --- a/gcc/ada/par-ch13.adb +++ b/gcc/ada/par-ch13.adb @@ -632,6 +632,77 @@ package body Ch13 is return Aspects; end Get_Aspect_Specifications; + ----------------------------- + -- P_Attribute_Designators -- + ----------------------------- + + function P_Attribute_Designators (Initial_Prefix : Node_Id) return Node_Id + is + Accumulator : Node_Id := Initial_Prefix; + Designator : Name_Id; + begin + while Token = Tok_Apostrophe loop + + Scan; -- past apostrophe + + Designator := No_Name; + + if Token = Tok_Identifier then + Designator := Token_Name; + + -- Note that the parser must complain in case of an internal + -- attribute name that comes from source since internal names are + -- meant to be used only by the compiler. + + if not Is_Attribute_Name (Designator) + and then (not Is_Internal_Attribute_Name (Designator) + or else Comes_From_Source (Token_Node)) + then + Signal_Bad_Attribute; + end if; + + if Style_Check then + Style.Check_Attribute_Name (False); + end if; + + -- Here for case of attribute designator is not an identifier + + else + if Token = Tok_Delta then + Designator := Name_Delta; + + elsif Token = Tok_Digits then + Designator := Name_Digits; + + elsif Token = Tok_Access then + Designator := Name_Access; + + else + Error_Msg_AP ("attribute designator expected"); + raise Error_Resync; + end if; + + if Style_Check then + Style.Check_Attribute_Name (True); + end if; + end if; + + -- Here we have an OK attribute scanned, and the corresponding + -- Attribute identifier node is stored in Designator. + + declare + Temp : constant Node_Id := Accumulator; + begin + Accumulator := New_Node (N_Attribute_Reference, Prev_Token_Ptr); + Set_Prefix (Accumulator, Temp); + end; + Set_Attribute_Name (Accumulator, Designator); + Scan; + end loop; + + return Accumulator; + end P_Attribute_Designators; + -------------------------------------------- -- 13.1 Representation Clause (also I.7) -- -------------------------------------------- @@ -674,8 +745,6 @@ package body Ch13 is function P_Representation_Clause return Node_Id is For_Loc : Source_Ptr; Name_Node : Node_Id; - Prefix_Node : Node_Id; - Attr_Name : Name_Id; Identifier_Node : Node_Id; Rep_Clause_Node : Node_Id; Expr_Node : Node_Id; @@ -693,8 +762,7 @@ package body Ch13 is -- Check case of qualified name to give good error message if Token = Tok_Dot then - Error_Msg_SC - ("representation clause requires simple name!"); + Error_Msg_SC ("representation clause requires simple name!"); loop exit when Token /= Tok_Dot; @@ -706,80 +774,28 @@ package body Ch13 is -- Attribute Definition Clause if Token = Tok_Apostrophe then + Name_Node := P_Attribute_Designators (Identifier_Node); - -- Allow local names of the form a'b'.... This enables - -- us to parse class-wide streams attributes correctly. - - Name_Node := Identifier_Node; - while Token = Tok_Apostrophe loop - - Scan; -- past apostrophe - - Identifier_Node := Token_Node; - Attr_Name := No_Name; - - if Token = Tok_Identifier then - Attr_Name := Token_Name; - - -- Note that the parser must complain in case of an internal - -- attribute name that comes from source since internal names - -- are meant to be used only by the compiler. - - if not Is_Attribute_Name (Attr_Name) - and then (not Is_Internal_Attribute_Name (Attr_Name) - or else Comes_From_Source (Token_Node)) - then - Signal_Bad_Attribute; - end if; - - if Style_Check then - Style.Check_Attribute_Name (False); - end if; - - -- Here for case of attribute designator is not an identifier - - else - if Token = Tok_Delta then - Attr_Name := Name_Delta; - - elsif Token = Tok_Digits then - Attr_Name := Name_Digits; + -- Check for Address clause which needs to be marked for use in + -- optimizing performance of Exp_Util.Following_Address_Clause. - elsif Token = Tok_Access then - Attr_Name := Name_Access; - - else - Error_Msg_AP ("attribute designator expected"); - raise Error_Resync; - end if; - - if Style_Check then - Style.Check_Attribute_Name (True); - end if; - end if; - - -- Here we have an OK attribute scanned, and the corresponding - -- Attribute identifier node is stored in Ident_Node. - - Prefix_Node := Name_Node; - Name_Node := New_Node (N_Attribute_Reference, Prev_Token_Ptr); - Set_Prefix (Name_Node, Prefix_Node); - Set_Attribute_Name (Name_Node, Attr_Name); - Scan; - - -- Check for Address clause which needs to be marked for use in - -- optimizing performance of Exp_Util.Following_Address_Clause. + declare + Cursor : Node_Id := Name_Node; + begin + while Nkind (Prefix (Cursor)) = N_Attribute_Reference loop + Cursor := Prefix (Cursor); + end loop; - if Attr_Name = Name_Address - and then Nkind (Prefix_Node) = N_Identifier + if Attribute_Name (Cursor) = Name_Address + and then Nkind (Prefix (Cursor)) = N_Identifier then - Set_Name_Table_Boolean1 (Chars (Prefix_Node), True); + Set_Name_Table_Boolean1 (Chars (Prefix (Cursor)), True); end if; - end loop; + end; Rep_Clause_Node := New_Node (N_Attribute_Definition_Clause, For_Loc); - Set_Name (Rep_Clause_Node, Prefix_Node); - Set_Chars (Rep_Clause_Node, Attr_Name); + Set_Name (Rep_Clause_Node, Prefix (Name_Node)); + Set_Chars (Rep_Clause_Node, Attribute_Name (Name_Node)); T_Use; Expr_Node := P_Expression_No_Right_Paren; diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb index a6418a5..2be3670 100644 --- a/gcc/ada/par-ch6.adb +++ b/gcc/ada/par-ch6.adb @@ -128,7 +128,8 @@ package body Ch6 is -- This routine scans out a subprogram declaration, subprogram body, -- subprogram renaming declaration or subprogram generic instantiation. - -- It also handles the new Ada 2012 expression function form + -- It also handles the new Ada 2012 expression function form, and the GNAT + -- extension for direct attribute definition. -- SUBPROGRAM_DECLARATION ::= -- SUBPROGRAM_SPECIFICATION @@ -141,6 +142,9 @@ package body Ch6 is -- SUBPROGRAM_SPECIFICATION ::= -- procedure DEFINING_PROGRAM_UNIT_NAME PARAMETER_PROFILE -- | function DEFINING_DESIGNATOR PARAMETER_AND_RESULT_PROFILE + -- | procedure LOCAL_NAME'ATTRIBUTE_DESIGNATOR PARAMETER_PROFILE + -- | function LOCAL_NAME'ATTRIBUTE_DESIGNATOR + -- PARAMETER_AND_RESULT_PROFILE -- PARAMETER_PROFILE ::= [FORMAL_PART] @@ -190,6 +194,13 @@ package body Ch6 is function Contains_Import_Aspect (Aspects : List_Id) return Boolean; -- Return True if Aspects contains an Import aspect. + procedure Rewrite_Entity_If_Direct_Attribute_Def + (Name : Node_Id; Spec : Node_Id); + -- In case of direct attribute definitions this procedure rewrites the + -- defining unit name of the specification node with a new entity. It is + -- essential to maintain the information that the original node comes + -- from a direct attribute definition. + ---------------------------- -- Contains_Import_Aspect -- ---------------------------- @@ -208,6 +219,39 @@ package body Ch6 is return False; end Contains_Import_Aspect; + -------------------------------------------- + -- Rewrite_Entity_If_Direct_Attribute_Def -- + -------------------------------------------- + + procedure Rewrite_Entity_If_Direct_Attribute_Def + (Name : Node_Id; Spec : Node_Id) + is + New_Entity, Copy_Spec : Node_Id; + begin + if Nkind (Name) = N_Attribute_Reference + and then Is_Direct_Attribute_Definition_Name (Attribute_Name (Name)) + then + -- Note that, this workaround is needed to retain the info that + -- the current subprogram comes from a direct attribute + -- definition. Otherwise, we would need to add an entity flag + -- Is_Constructor. Currently this flag already exists and could be + -- misleading as it refer to CPP constructors ??? + + Copy_Spec := New_Copy (Spec); + + New_Entity := Make_Defining_Identifier (Sloc (Name), + Direct_Attribute_Definition_Name + (Prefix (Name), Attribute_Name (Name))); + Set_Comes_From_Source (New_Entity); + Set_Parent (New_Entity, Copy_Spec); + + Set_Defining_Unit_Name (Copy_Spec, New_Entity); + Rewrite (Spec, Copy_Spec); + end if; + end Rewrite_Entity_If_Direct_Attribute_Def; + + -- Local variables + Specification_Node : Node_Id; Name_Node : Node_Id; Aspects : List_Id; @@ -232,6 +276,8 @@ package body Ch6 is Is_Overriding : Boolean := False; Not_Overriding : Boolean := False; + -- Start of processing for P_Subprogram + begin -- Set up scope stack entry. Note that the Labl field will be set later @@ -343,11 +389,19 @@ package body Ch6 is Name_Node := P_Defining_Program_Unit_Name; end if; + -- Deal with direct attribute definition in subprogram specification + + if Token = Tok_Apostrophe then + Error_Msg_GNAT_Extension ("direct attribute definition", Token_Ptr); + + Name_Node := P_Attribute_Designators (Name_Node); + end if; + Scopes (Scope.Last).Labl := Name_Node; Ignore (Tok_Colon); -- Deal with generic instantiation, the one case in which we do not - -- have a subprogram specification as part of whatever we are parsing + -- have a subprogram specification as part of whatever we are parsing. if Token = Tok_Is then Save_Scan_State (Scan_State); -- at the IS @@ -940,6 +994,9 @@ package body Ch6 is Parse_Decls_Begin_End (Body_Node); end if; + Rewrite_Entity_If_Direct_Attribute_Def + (Name_Node, Specification_Node); + return Body_Node; end Scan_Body_Or_Expression_Function; end if; @@ -952,6 +1009,9 @@ package body Ch6 is Set_Specification (Decl_Node, Specification_Node); Aspects := Get_Aspect_Specifications (Semicolon => False); + Rewrite_Entity_If_Direct_Attribute_Def + (Name_Node, Specification_Node); + -- Aspects may be present on a subprogram body. The source parsed -- so far is that of its specification. Go parse the body and attach -- the collected aspects, if any, to the body. diff --git a/gcc/ada/par-endh.adb b/gcc/ada/par-endh.adb index 8166705..8637e07 100644 --- a/gcc/ada/par-endh.adb +++ b/gcc/ada/par-endh.adb @@ -156,12 +156,12 @@ package body Endh is function Same_Label (Label1, Label2 : Node_Id) return Boolean; -- This function compares the two names associated with the given nodes. -- If they are both simple (i.e. have Chars fields), then they have to - -- be the same name. Otherwise they must both be N_Selected_Component - -- nodes, referring to the same set of names, or Label1 is an N_Designator - -- referring to the same set of names as the N_Defining_Program_Unit_Name - -- in Label2. Any other combination returns False. This routine is used - -- to compare the End_Labl scanned from the End line with the saved label - -- value in the scope stack. + -- be the same name. If they are both N_Selected_Component or + -- N_Attribute_Reference nodes, they must refer to the same set of names. + -- Otherwise, Label1 must be a N_Designator referring to the same set of + -- names as the N_Defining_Program_Unit_Name in Label2. Any other + -- combination returns False. This routine is used to compare the End_Labl + -- scanned from the End line with the saved label value in the scope stack. --------------- -- Check_End -- @@ -270,6 +270,16 @@ package body Endh is end if; End_Labl := P_Designator; + + -- Case of direct attribute definition + + if Token = Tok_Apostrophe then + Error_Msg_GNAT_Extension + ("direct attribute definition", Token_Ptr); + + End_Labl := P_Attribute_Designators (End_Labl); + end if; + End_Labl_Present := True; -- We have now scanned out a name. Here is where we do a check @@ -1359,6 +1369,12 @@ package body Endh is return Same_Label (Prefix (Label1), Prefix (Label2)) and then Same_Label (Selector_Name (Label1), Selector_Name (Label2)); + elsif Nkind (Label1) = N_Attribute_Reference + and then Nkind (Label2) = N_Attribute_Reference + then + return Same_Label (Prefix (Label1), Prefix (Label2)) and then + Attribute_Name (Label1) = Attribute_Name (Label2); + elsif Nkind (Label1) = N_Designator and then Nkind (Label2) = N_Defining_Program_Unit_Name then diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb index 8ced09d..6fc4bed 100644 --- a/gcc/ada/par.adb +++ b/gcc/ada/par.adb @@ -1019,6 +1019,16 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is package Ch13 is function P_Representation_Clause return Node_Id; + function P_Attribute_Designators + (Initial_Prefix : Node_Id) return Node_Id; + -- This procedure parses trailing apostrophes and attribute designators, + -- i.e., the "'b'c..." suffix in "a'b'c...". "a" must have already been + -- parsed into Initial_Prefix and the scan pointer must be pointing + -- right past "a". If no apostrophe is found we just return + -- Initial_Prefix, otherwise the return value is a chain of + -- N_Attribute_Reference nodes, nested via the Prefix field and ending + -- with Initial_Prefix. + function Aspect_Specifications_Present (Strict : Boolean := Ada_Version < Ada_2012) return Boolean; -- This function tests whether the next keyword is WITH followed by diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads index c82af11..ee529e1 100644 --- a/gcc/ada/rtsfind.ads +++ b/gcc/ada/rtsfind.ads @@ -1900,6 +1900,7 @@ package Rtsfind is RE_W_U24, -- System.Stream_Attributes RE_W_WC, -- System.Stream_Attributes RE_W_WWC, -- System.Stream_Attributes + RE_W_80IEEE, -- System.Stream_Attributes RE_Storage_Array_Input, -- System.Strings.Stream_Ops RE_Storage_Array_Input_Blk_IO, -- System.Strings.Stream_Ops @@ -3565,6 +3566,7 @@ package Rtsfind is RE_W_U24 => System_Stream_Attributes, RE_W_WC => System_Stream_Attributes, RE_W_WWC => System_Stream_Attributes, + RE_W_80IEEE => System_Stream_Attributes, RE_Storage_Array_Input => System_Strings_Stream_Ops, RE_Storage_Array_Input_Blk_IO => System_Strings_Stream_Ops, diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index e9e245a..20270c2 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -3957,6 +3957,13 @@ package body Sem_Attr is Error_Attr_P ("prefix of % attribute must be object of discriminated type"); + ----------------- + -- Constructor -- + ----------------- + + when Attribute_Constructor => + Error_Attr_P ("attribute% can only be used to define constructors"); + --------------- -- Copy_Sign -- --------------- @@ -5180,12 +5187,17 @@ package body Sem_Attr is Expr : Entity_Id; begin if not All_Extensions_Allowed then - Error_Msg_GNAT_Extension ("Make attribute", Loc); + Error_Msg_GNAT_Extension ("attribute %", Loc); return; end if; + Check_Type; Set_Etype (N, Etype (P)); + if not Needs_Construction (Entity (P)) then + Error_Msg_NE ("no available constructor for&", N, Entity (P)); + end if; + if Present (Expressions (N)) then Expr := First (Expressions (N)); while Present (Expr) loop @@ -5197,6 +5209,9 @@ package body Sem_Attr is Next (Expr); end loop; + + elsif not Has_Default_Constructor (Entity (P)) then + Error_Msg_NE ("no default constructor for&", N, Entity (P)); end if; end; @@ -11144,6 +11159,7 @@ package body Sem_Attr is | Attribute_Class | Attribute_Code_Address | Attribute_Compiler_Version + | Attribute_Constructor | Attribute_Count | Attribute_Default_Bit_Order | Attribute_Default_Scalar_Storage_Order @@ -12477,70 +12493,6 @@ package body Sem_Attr is Set_Address_Taken (Entity (P)); end if; - if Nkind (P) = N_Slice then - - -- Arr (X .. Y)'address is identical to Arr (X)'address, - -- even if the array is packed and the slice itself is not - -- addressable. Transform the prefix into an indexed component. - - -- Note that the transformation is safe only if we know that - -- the slice is non-null. That is because a null slice can have - -- an out of bounds index value. - - -- Right now, gigi blows up if given 'Address on a slice as a - -- result of some incorrect freeze nodes generated by the front - -- end, and this covers up that bug in one case, but the bug is - -- likely still there in the cases not handled by this code ??? - - -- It's not clear what 'Address *should* return for a null - -- slice with out of bounds indexes, this might be worth an ARG - -- discussion ??? - - -- One approach would be to do a length check unconditionally, - -- and then do the transformation below unconditionally, but - -- analyze with checks off, avoiding the problem of the out of - -- bounds index. This approach would interpret the address of - -- an out of bounds null slice as being the address where the - -- array element would be if there was one, which is probably - -- as reasonable an interpretation as any ??? - - declare - Loc : constant Source_Ptr := Sloc (P); - D : constant Node_Id := Discrete_Range (P); - Lo : Node_Id; - - begin - if Is_Entity_Name (D) - and then - Not_Null_Range - (Type_Low_Bound (Entity (D)), - Type_High_Bound (Entity (D))) - then - Lo := - Make_Attribute_Reference (Loc, - Prefix => (New_Occurrence_Of (Entity (D), Loc)), - Attribute_Name => Name_First); - - elsif Nkind (D) = N_Range - and then Not_Null_Range (Low_Bound (D), High_Bound (D)) - then - Lo := Low_Bound (D); - - else - Lo := Empty; - end if; - - if Present (Lo) then - Rewrite (P, - Make_Indexed_Component (Loc, - Prefix => Relocate_Node (Prefix (P)), - Expressions => New_List (Lo))); - - Analyze_And_Resolve (P); - end if; - end; - end if; - ------------------ -- Body_Version -- ------------------ @@ -12805,45 +12757,43 @@ package body Sem_Attr is and then Scope (Op) = Standard_Standard and then not Strict then - declare - Op_Chars : constant Any_Operator_Name := Chars (Op); - -- Nonassociative ops like division are unlikely - -- to come up in practice, but they are legal. - begin - case Op_Chars is - when Name_Op_Add - | Name_Op_Subtract - | Name_Op_Multiply - | Name_Op_Divide - | Name_Op_Expon - => - return Is_Numeric_Type (Typ); - - when Name_Op_Mod | Name_Op_Rem => - return Is_Numeric_Type (Typ) - and then Is_Discrete_Type (Typ); - - when Name_Op_And | Name_Op_Or | Name_Op_Xor => - -- No Boolean array operators in Standard - return Is_Boolean_Type (Typ) - or else Is_Modular_Integer_Type (Typ); + -- Nonassociative ops like division are unlikely to + -- come up in practice, but they are legal. + + case Any_Operator_Name'(Chars (Op)) is + when Name_Op_Add + | Name_Op_Subtract + | Name_Op_Multiply + | Name_Op_Divide + | Name_Op_Expon + => + return Is_Numeric_Type (Typ); + + when Name_Op_Mod | Name_Op_Rem => + return Is_Numeric_Type (Typ) + and then Is_Discrete_Type (Typ); + + when Name_Op_And | Name_Op_Or | Name_Op_Xor => + -- No Boolean array operators in Standard + return Is_Boolean_Type (Typ) + or else Is_Modular_Integer_Type (Typ); + + when Name_Op_Concat => + return Is_Array_Type (Typ) + and then Number_Dimensions (Typ) = 1; + + when Name_Op_Eq | Name_Op_Ne + | Name_Op_Lt | Name_Op_Le + | Name_Op_Gt | Name_Op_Ge + => + return Is_Boolean_Type (Typ); + + when Name_Op_Abs | Name_Op_Not => + -- unary ops were already handled + + raise Program_Error; + end case; - when Name_Op_Concat => - return Is_Array_Type (Typ) - and then Number_Dimensions (Typ) = 1; - - when Name_Op_Eq | Name_Op_Ne - | Name_Op_Lt | Name_Op_Le - | Name_Op_Gt | Name_Op_Ge - => - return Is_Boolean_Type (Typ); - - when Name_Op_Abs | Name_Op_Not => - -- unary ops were already handled - pragma Assert (False); - raise Program_Error; - end case; - end; else return False; end if; diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb index 58a4beb..107e27e 100644 --- a/gcc/ada/sem_aux.adb +++ b/gcc/ada/sem_aux.adb @@ -184,9 +184,6 @@ package body Sem_Aux is -- Normal case, search enclosing scopes - -- Note: the test for Present (S) should not be required, it defends - -- against an ill-formed tree. - S := Scope (Ent); loop -- If we somehow got an empty value for Scope, the tree must be diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index deb19ee..702939a 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -599,8 +599,8 @@ package body Sem_Ch12 is -- whose views can change between the point of instantiation and the point -- of instantiation of the body. In addition, mark the generic renamings -- as generic actuals, so that they are not compatible with other actuals. - -- Recurse on an actual that is a formal package whose declaration has - -- a box. + -- For an instantiation of a formal package that is declared with a box or + -- contains defaulted parameters, make the corresponding actuals visible. function Component_Type_For_Private_View (T : Entity_Id) return Entity_Id; -- Return the component type of array type T, with the following addition: @@ -944,6 +944,13 @@ package body Sem_Ch12 is -- Restore suffix 'P' to primitives of Prims_List and leave Prims_List -- set to No_Elist. + procedure Restore_Private_Views (Pack_Id : Entity_Id; Is_Package : Boolean); + -- Restore the private views of external types, and unmark the generic + -- renamings of actuals, so that they become compatible subtypes again. + -- Reset the visibility of the actuals (some of them may have been made + -- visible by Check_Generic_Actuals). For subprograms, Pack_Id is the + -- wrapper package built to hold the renamings and Is_Package is False. + procedure Set_Instance_Env (Gen_Unit : Entity_Id; Act_Unit : Entity_Id); @@ -958,6 +965,10 @@ package body Sem_Ch12 is -- Associate analyzed generic parameter with corresponding instance. Used -- for semantic checks at instantiation time. + procedure Switch_View (T : Entity_Id); + -- Switch the partial and full views of a type, as well as those of its + -- private dependents (i.e. its subtypes and derived types). + function True_Parent (N : Node_Id) return Node_Id; -- For a subunit, return parent of corresponding stub, else return -- parent of node. @@ -1080,18 +1091,6 @@ package body Sem_Ch12 is Table_Increment => 100, Table_Name => "Instance_Envs"); - procedure Restore_Private_Views - (Pack_Id : Entity_Id; - Is_Package : Boolean := True); - -- Restore the private views of external types, and unmark the generic - -- renamings of actuals, so that they become compatible subtypes again. - -- For subprograms, Pack_Id is the package constructed to hold the - -- renamings. - - procedure Switch_View (T : Entity_Id); - -- Switch the partial and full views of a type and its private - -- dependents (i.e. its subtypes and derived types). - ------------------------------------ -- Structures for Error Reporting -- ------------------------------------ @@ -1607,8 +1606,8 @@ package body Sem_Ch12 is return Result : Actual_Rec do case Nkind (Un_Formal) is when N_Formal_Object_Declaration => - if Present (Default_Expression (Un_Formal)) then - Result := (Name_Exp, Default_Expression (Un_Formal)); + if Present (Expression (Un_Formal)) then + Result := (Name_Exp, Expression (Un_Formal)); end if; when N_Formal_Type_Declaration => if Present (Default_Subtype_Mark (Un_Formal)) then @@ -1663,18 +1662,14 @@ package body Sem_Ch12 is if Box_Present (Src_Assoc) then Assoc.Actual := (Kind => Box_Actual); - if False then -- ??? - -- Disable this for now, because we have various - -- code that needs to be updated. - Error_Msg_N - ("box requires named notation", Src_Assoc); - end if; + Error_Msg_N ("box requires named notation", Src_Assoc); else Assoc.Actual := (Name_Exp, Explicit_Generic_Actual_Parameter (Src_Assoc)); pragma Assert (Present (Assoc.Actual.Name_Exp)); end if; + Assoc.Actual_Origin := From_Explicit_Actual; Next (Src_Assoc); @@ -2557,7 +2552,7 @@ package body Sem_Ch12 is (Defining_Identifier (Assoc.Un_Formal), Sloc (N)), Explicit_Generic_Actual_Parameter => - New_Copy_Tree (Default_Expression (Assoc.Un_Formal)))); + New_Copy_Tree (Expression (Assoc.Un_Formal)))); end if; end if; @@ -3361,7 +3356,7 @@ package body Sem_Ch12 is --------------------------------------- procedure Analyze_Formal_Object_Declaration (N : Node_Id) is - E : constant Node_Id := Default_Expression (N); + E : constant Node_Id := Expression (N); Id : constant Node_Id := Defining_Identifier (N); K : Entity_Kind; @@ -5696,7 +5691,7 @@ package body Sem_Ch12 is Check_Formal_Packages (Act_Decl_Id); Restore_Hidden_Primitives (Vis_Prims_List); - Restore_Private_Views (Act_Decl_Id); + Restore_Private_Views (Act_Decl_Id, Is_Package => True); Inherit_Context (Gen_Decl, N); @@ -7218,7 +7213,7 @@ package body Sem_Ch12 is if not Is_Intrinsic_Subprogram (Act_Decl_Id) then Inherit_Context (Gen_Decl, N); - Restore_Private_Views (Pack_Id, False); + Restore_Private_Views (Pack_Id, Is_Package => False); -- If the context requires a full instantiation, mark node for -- subsequent construction of the body. @@ -8571,9 +8566,6 @@ package body Sem_Ch12 is Set_Is_Generic_Actual_Type (Full_View (E)); end if; - Set_Is_Hidden (E, False); - Set_Is_Potentially_Use_Visible (E, In_Use (Instance)); - -- We constructed the generic actual type as a subtype of the -- supplied type. This means that it normally would not inherit -- subtype specific attributes of the actual, which is wrong for @@ -8627,21 +8619,15 @@ package body Sem_Ch12 is (Renamed_Entity (E), Is_Formal_Box => Box_Present (Parent (Associated_Formal_Package (E)))); - - Set_Is_Hidden (E, False); end if; - - -- If this is a subprogram instance (in a wrapper package) the - -- actual is fully visible. - - elsif Is_Wrapper_Package (Instance) then - Set_Is_Hidden (E, False); + end if; -- If the formal package is declared with a box, or if the formal - -- parameter is defaulted, it is visible in the body. + -- parameter is defaulted, the actual is visible in the instance. - elsif Is_Formal_Box or else Is_Visible_Formal (E) then + if Is_Formal_Box or else Is_Visible_Formal (E) then Set_Is_Hidden (E, False); + Set_Is_Potentially_Use_Visible (E, In_Use (Instance)); end if; -- Check directly the type of the actual objects, including the @@ -11660,8 +11646,10 @@ package body Sem_Ch12 is null; elsif Present (Associated_Formal_Package (E)) then - Check_Generic_Actuals (Renamed_Entity (E), True); - Set_Is_Hidden (E, False); + Check_Generic_Actuals + (Renamed_Entity (E), + Is_Formal_Box => + Box_Present (Parent (Associated_Formal_Package (E)))); -- Find formal package in generic unit that corresponds to -- (instance of) formal package in instance. @@ -12450,7 +12438,7 @@ package body Sem_Ch12 is (Nkind (Actual_Of_Formal) = N_Package_Instantiation); end if; - Next (Actual_Of_Formal); + Next_Non_Pragma (Actual_Of_Formal); -- A formal subprogram may be overloaded, so advance in -- the list of actuals to make sure we do not match two @@ -13236,7 +13224,7 @@ package body Sem_Ch12 is end if; end; - elsif Present (Default_Expression (Formal)) then + elsif Present (Expression (Formal)) then -- Use default to construct declaration @@ -13254,7 +13242,7 @@ package body Sem_Ch12 is Null_Exclusion_Present => Null_Exclusion_Present (Formal), Object_Definition => Def, Expression => New_Copy_Tree - (Default_Expression (Formal))); + (Expression (Formal))); Copy_Ghost_Aspect (Formal, To => Decl_Node); Set_Corresponding_Generic_Association @@ -13679,7 +13667,7 @@ package body Sem_Ch12 is Set_Defining_Unit_Name (Act_Body, Act_Body_Name); Set_Corresponding_Spec (Act_Body, Act_Decl_Id); - Check_Generic_Actuals (Act_Decl_Id, False); + Check_Generic_Actuals (Act_Decl_Id, Is_Formal_Box => False); Check_Initialized_Types; -- Install primitives hidden at the point of the instantiation but @@ -13927,7 +13915,7 @@ package body Sem_Ch12 is -- the two mechanisms swap exactly the same entities, in particular -- the private entities dependent on the primary private entities. - Restore_Private_Views (Act_Decl_Id); + Restore_Private_Views (Act_Decl_Id, Is_Package => True); -- Remove the current unit from visibility if this is an instance -- that is not elaborated on the fly for inlining purposes. @@ -14174,7 +14162,7 @@ package body Sem_Ch12 is Set_Corresponding_Spec (Act_Body, Act_Decl_Id); Set_Has_Completion (Act_Decl_Id); - Check_Generic_Actuals (Pack_Id, False); + Check_Generic_Actuals (Pack_Id, Is_Formal_Box => False); -- Generate a reference to link the visible subprogram instance to -- the generic body, which for navigation purposes is the only @@ -14245,7 +14233,7 @@ package body Sem_Ch12 is Inherit_Context (Gen_Body, Inst_Node); - Restore_Private_Views (Pack_Id, False); + Restore_Private_Views (Pack_Id, Is_Package => False); if Par_Installed then Remove_Parent (In_Body => True); @@ -17093,10 +17081,18 @@ package body Sem_Ch12 is Saved : Instance_Env renames Instance_Envs.Table (Instance_Envs.Last); begin - if No (Current_Instantiated_Parent.Act_Id) then - -- Restore environment after subprogram inlining + -- Restore environment after subprogram inlining - Restore_Private_Views (Empty); + if No (Current_Instantiated_Parent.Act_Id) then + declare + M : Elmt_Id; + begin + M := First_Elmt (Exchanged_Views); + while Present (M) loop + Exchange_Declarations (Node (M)); + Next_Elmt (M); + end loop; + end; end if; Current_Instantiated_Parent := Saved.Instantiated_Parent; @@ -17115,9 +17111,7 @@ package body Sem_Ch12 is -- Restore_Private_Views -- --------------------------- - procedure Restore_Private_Views - (Pack_Id : Entity_Id; - Is_Package : Boolean := True) + procedure Restore_Private_Views (Pack_Id : Entity_Id; Is_Package : Boolean) is M : Elmt_Id; E : Entity_Id; @@ -17136,6 +17130,7 @@ package body Sem_Ch12 is procedure Restore_Nested_Formal (Formal : Entity_Id) is pragma Assert (Ekind (Formal) = E_Package); Ent : Entity_Id; + begin if Present (Renamed_Entity (Formal)) and then Denotes_Formal_Package (Renamed_Entity (Formal), True) @@ -17198,16 +17193,13 @@ package body Sem_Ch12 is Next_Elmt (M); end loop; - if No (Pack_Id) then - return; - end if; - -- Make the generic formal parameters private, and make the formal types -- into subtypes of the actuals again. E := First_Entity (Pack_Id); while Present (E) loop - Set_Is_Hidden (E, True); + Set_Is_Hidden (E); + Set_Is_Potentially_Use_Visible (E, False); if Is_Type (E) and then Nkind (Parent (E)) = N_Subtype_Declaration @@ -17231,6 +17223,7 @@ package body Sem_Ch12 is (Entity (Subtype_Indication (Parent (E)))) then null; + else Set_Is_Generic_Actual_Type (E, False); @@ -17275,7 +17268,7 @@ package body Sem_Ch12 is -- If the actual is itself a formal package for the enclosing -- generic, or the actual for such a formal package, it remains -- visible on exit from the instance, and therefore nothing needs - -- to be done either, except to keep it accessible. + -- to be done either. if Is_Package and then Renamed_Entity (E) = Pack_Id then exit; @@ -17286,7 +17279,7 @@ package body Sem_Ch12 is elsif Denotes_Formal_Package (Renamed_Entity (E), True, Pack_Id) then - Set_Is_Hidden (E, False); + null; else declare @@ -17301,8 +17294,8 @@ package body Sem_Ch12 is exit when Ekind (Id) = E_Package and then Renamed_Entity (Id) = Act_P; - Set_Is_Hidden (Id, True); - Set_Is_Potentially_Use_Visible (Id, In_Use (Act_P)); + Set_Is_Hidden (Id); + Set_Is_Potentially_Use_Visible (Id, False); if Ekind (Id) = E_Package then Restore_Nested_Formal (Id); diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index f7be890..31af1bb 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -442,11 +442,6 @@ package body Sem_Ch13 is Off : Boolean; -- Whether the address is offset within Y in the second case - - Alignment_Checks_Suppressed : Boolean; - -- Whether alignment checks are suppressed by an active scope suppress - -- setting. We need to save the value in order to be able to reuse it - -- after the back end has been run. end record; package Address_Clause_Checks is new Table.Table ( @@ -457,26 +452,6 @@ package body Sem_Ch13 is Table_Increment => 200, Table_Name => "Address_Clause_Checks"); - function Alignment_Checks_Suppressed - (ACCR : Address_Clause_Check_Record) return Boolean; - -- Return whether the alignment check generated for the address clause - -- is suppressed. - - --------------------------------- - -- Alignment_Checks_Suppressed -- - --------------------------------- - - function Alignment_Checks_Suppressed - (ACCR : Address_Clause_Check_Record) return Boolean - is - begin - if Checks_May_Be_Suppressed (ACCR.X) then - return Is_Check_Suppressed (ACCR.X, Alignment_Check); - else - return ACCR.Alignment_Checks_Suppressed; - end if; - end Alignment_Checks_Suppressed; - ----------------------------------------- -- Adjust_Record_For_Reverse_Bit_Order -- ----------------------------------------- @@ -5041,16 +5016,6 @@ package body Sem_Ch13 is Analyze_Aspect_Implicit_Dereference; goto Continue; - when Aspect_Constructor => - if not All_Extensions_Allowed then - Error_Msg_Name_1 := Nam; - Error_Msg_GNAT_Extension ("aspect %", Loc); - goto Continue; - end if; - - Set_Constructor_Name (E, Expr); - Set_Needs_Construction (E); - -- Dimension when Aspect_Dimension => @@ -7096,11 +7061,15 @@ package body Sem_Ch13 is end if; end; - -- Entity has delayed freeze, so we will generate an + -- The entity has delayed freeze, so we will generate an -- alignment check at the freeze point unless suppressed. + -- We will unconditionally generate it when the alignment + -- is specified in addition to the address, to compensate + -- for the check being suppressed by default on machines + -- that do not need strict alignment of memory accesses. - if not Range_Checks_Suppressed (U_Ent) - and then not Alignment_Checks_Suppressed (U_Ent) + if not Alignment_Checks_Suppressed (U_Ent) + or else Present (Alignment_Clause (U_Ent)) then Set_Check_Address_Alignment (N); end if; @@ -7175,6 +7144,14 @@ package body Sem_Ch13 is if Is_Array_Type (U_Ent) then Set_Alignment (Base_Type (U_Ent), Align); end if; + + -- See the Attribute_Address case above for the rationale + + if not Is_Type (U_Ent) + and then Present (Address_Clause (U_Ent)) + then + Set_Check_Address_Alignment (Address_Clause (U_Ent)); + end if; end if; end Alignment; @@ -7844,7 +7821,7 @@ package body Sem_Ch13 is end if; end if; - -- For Object'Size, set Esize only + -- For objects, set Esize only else if Is_Elementary_Type (Etyp) @@ -7858,26 +7835,37 @@ package body Sem_Ch13 is Error_Msg_Uint_2 := UI_From_Int (System_Max_Integer_Size); Error_Msg_N - ("size for primitive object must be a power of 2 in " - & "the range ^-^", N); - end if; + ("size for elementary object must be a power of 2 " + & "in the range ^-^", N); - Set_Esize (U_Ent, Size); - end if; + -- As per RM 13.1(25/5), only a confirming size clause + -- (i.e. Size = Type'Object_Size) for aliased objects + -- of elementary types is required to be supported. + -- We reject nonconfirming clauses for these objects. - -- As of RM 13.1, only confirming size - -- (i.e. (Size = Esize (Etyp))) for aliased object of - -- elementary type must be supported. - -- GNAT rejects nonconfirming size for such object. + elsif Is_Aliased (U_Ent) + and then Is_Elementary_Type (Etyp) + and then Size /= Esize (Etyp) + then + Error_Msg_N + ("nonconfirming Size for aliased object is not " + & "supported", N); - if Is_Aliased (U_Ent) - and then Is_Elementary_Type (Etyp) - and then Known_Esize (U_Ent) - and then Size /= Esize (Etyp) - then - Error_Msg_N - ("nonconfirming Size for aliased object is not " - & "supported", N); + -- We also reject nonconfirming clauses for (nonaliased) + -- objects of floating-point types because smaller sizes + -- would require integer operations to access the objects + -- and larger sizes would require integer operations to + -- manipulate the padding bits. + + elsif Is_Floating_Point_Type (Etyp) + and then Size /= Esize (Etyp) + then + Error_Msg_N + ("nonconfirming Size for floating-point object is " + & "not supported", N); + end if; + + Set_Esize (U_Ent, Size); end if; -- Handle extension aspect 'Size'Class which allows for @@ -11753,8 +11741,7 @@ package body Sem_Ch13 is -- name, so we need to verify that one of these interpretations is -- the one available at the freeze point. - elsif A_Id in Aspect_Constructor - | Aspect_Destructor + elsif A_Id in Aspect_Destructor | Aspect_Input | Aspect_Output | Aspect_Read @@ -12050,8 +12037,7 @@ package body Sem_Ch13 is -- Special case, the expression of these aspects is just an entity -- that does not need any resolution, so just analyze. - when Aspect_Constructor - | Aspect_Input + when Aspect_Input | Aspect_Output | Aspect_Put_Image | Aspect_Read @@ -16670,9 +16656,8 @@ package body Sem_Ch13 is Y : Entity_Id; Off : Boolean) is - ACS : constant Boolean := Scope_Suppress.Suppress (Alignment_Check); begin - Address_Clause_Checks.Append ((N, X, A, Y, Off, ACS)); + Address_Clause_Checks.Append ((N, X, A, Y, Off)); end Register_Address_Clause_Check; ------------------------ @@ -17357,9 +17342,6 @@ package body Sem_Ch13 is => null; - when Aspect_Constructor => - null; - when Aspect_Dynamic_Predicate | Aspect_Ghost_Predicate | Aspect_Predicate @@ -19125,7 +19107,7 @@ package body Sem_Ch13 is -- Check for known value not multiple of alignment if No (ACCR.Y) then - if not Alignment_Checks_Suppressed (ACCR) + if Check_Address_Alignment (ACCR.N) and then X_Alignment /= 0 and then ACCR.A mod X_Alignment /= 0 then @@ -19170,7 +19152,7 @@ package body Sem_Ch13 is -- Note: we do not check the alignment if we gave a size -- warning, since it would likely be redundant. - elsif not Alignment_Checks_Suppressed (ACCR) + elsif Check_Address_Alignment (ACCR.N) and then Y_Alignment /= Uint_0 and then (Y_Alignment < X_Alignment diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 79986bb..233f823 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -5246,6 +5246,15 @@ package body Sem_Ch3 is and then Nkind (E) = N_Aggregate then Act_T := Etype (E); + + elsif Needs_Construction (T) + and then not Has_Init_Expression (N) + and then not Has_Default_Constructor (T) + and then not Suppress_Initialization (Id) + and then Comes_From_Source (N) + then + Error_Msg_NE ("no default constructor for&", + Object_Definition (N), T); end if; -- Check No_Wide_Characters restriction @@ -5944,6 +5953,8 @@ package body Sem_Ch3 is Set_Scalar_Range (Id, Scalar_Range (T)); Set_Digits_Value (Id, Digits_Value (T)); Set_Is_Constrained (Id, Is_Constrained (T)); + Set_Is_IEEE_Extended_Precision + (Id, Is_IEEE_Extended_Precision (T)); -- If the floating point type has dimensions, these will be -- inherited subsequently when Analyze_Dimensions is called. @@ -8206,10 +8217,14 @@ package body Sem_Ch3 is Set_Digits_Value (Implicit_Base, Digits_Value (Parent_Base)); Set_Float_Rep (Implicit_Base, Float_Rep (Parent_Base)); + Set_Is_IEEE_Extended_Precision + (Implicit_Base, Is_IEEE_Extended_Precision (Parent_Base)); if No_Constraint then Set_Digits_Value (Derived_Type, Digits_Value (Parent_Type)); end if; + Set_Is_IEEE_Extended_Precision + (Derived_Type, Is_IEEE_Extended_Precision (Parent_Base)); elsif Is_Fixed_Point_Type (Parent_Type) then diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 5e84889..b752a6b 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -3843,7 +3843,8 @@ package body Sem_Ch6 is -- user entities, as internally generated entitities might still need -- to be expanded (e.g. those generated for types). - if Present (Ghost_Config.Ignored_Ghost_Region) + if not CodePeer_Mode + and then Present (Ghost_Config.Ignored_Ghost_Region) and then Comes_From_Source (Body_Id) then Expander_Active := False; @@ -5029,7 +5030,9 @@ package body Sem_Ch6 is end if; <<Leave>> - if Present (Ghost_Config.Ignored_Ghost_Region) then + if not CodePeer_Mode + and then Present (Ghost_Config.Ignored_Ghost_Region) + then Expander_Active := Saved_EA; end if; @@ -5270,10 +5273,95 @@ package body Sem_Ch6 is -- both subprogram bodies and subprogram declarations (specs). function Analyze_Subprogram_Specification (N : Node_Id) return Entity_Id is + procedure Analyze_Direct_Attribute_Definition (Designator : Entity_Id); + -- This procedure checks whether the direct attribute definition for N + -- is correct for the given attribute name, and analyzes it. + function Is_Invariant_Procedure_Or_Body (E : Entity_Id) return Boolean; -- Determine whether entity E denotes the spec or body of an invariant -- procedure. + ----------------------------------------- + -- Analyze_Direct_Attribute_Definition -- + ----------------------------------------- + + procedure Analyze_Direct_Attribute_Definition (Designator : Entity_Id) is + Att_N : constant Node_Id := Original_Node (N); + Prefix_E : constant Entity_Id := + Get_Name_Entity_Id (Chars (Prefix (Defining_Unit_Name (Att_N)))); + Att_Name : constant Name_Id := + Attribute_Name (Defining_Unit_Name (Att_N)); + begin + pragma Assert (N /= Att_N); + + if not Is_Direct_Attribute_Definition_Name (Att_Name) then + Error_Msg_Name_1 := Att_Name; + Error_Msg_N + ("direct definition syntax not supported for attribute%", + Designator); + end if; + + -- Handle each kind of attribute separately + + case Att_Name is + + when Name_Constructor => + Error_Msg_Name_1 := Att_Name; + + -- No further action required in a subprogram body + + if Parent_Kind (N) not in N_Subprogram_Declaration then + return; + + elsif No (Prefix_E) or else not Is_Type (Prefix_E) then + Error_Msg_N + ("prefix& of attribute% must be a type", + Prefix (Defining_Unit_Name (Att_N))); + + elsif Ekind (Designator) /= E_Procedure then + Error_Msg_N + ("attribute% can only be specified to a procedure", N); + + elsif No (First_Formal (Designator)) + or else Etype (First_Formal (Designator)) /= Prefix_E + or else Ekind (First_Formal (Designator)) + /= E_In_Out_Parameter + then + declare + Problem : constant Source_Ptr := + (if No (First_Formal (Designator)) + then Sloc (N) + else Sloc (First_Formal (Designator))); + begin + Error_Msg_Node_1 := Defining_Unit_Name (Att_N); + Error_Msg_Node_2 := Prefix_E; + Error_Msg + ("& must have a first IN OUT formal of type&", Problem); + end; + + elsif Is_Frozen (Prefix_E) + or else Current_Scope /= Scope (Prefix_E) + then + Error_Msg_Sloc := Sloc (Freeze_Node (Prefix_E)); + Error_Msg_N + ("& must be defined before freezing#", Designator); + + elsif Parent_Kind (Enclosing_Package_Or_Subprogram (Designator)) + /= N_Package_Specification + then + Error_Msg_N + ("& is required to be a primitive operation", Designator); + + else + Set_Needs_Construction (Prefix_E); + end if; + + when others => + null; + + end case; + end Analyze_Direct_Attribute_Definition; + ------------------------------------ -- Is_Invariant_Procedure_Or_Body -- ------------------------------------ @@ -5416,89 +5504,6 @@ package body Sem_Ch6 is End_Scope; - -- Register the subprogram in a Constructor_List when it is a valid - -- constructor. - - if All_Extensions_Allowed - and then Present (First_Formal (Designator)) - then - - declare - First_Form_Type : constant Entity_Id := - Etype (First_Formal (Designator)); - - Construct : Elmt_Id; - begin - -- Valid constructors have a "controlling" formal of a type - -- with the Constructor aspect specified. Additionally, the - -- subprogram name must match value described by the aspect. - - -- Additionally, constructor declarations must exist within the - -- same scope as the type declaration and before the type is - -- frozen. - - -- For example: - -- - -- type Foo is null record with Constructor => Bar; - -- - -- procedure Bar (Self : in out Foo); - -- - - if Present (Constructor_Name (First_Form_Type)) - and then Current_Scope = Scope (First_Form_Type) - and then Chars (Constructor_Name (First_Form_Type)) - = Chars (Designator) - and then Ekind (Designator) = E_Procedure - and then Nkind (Parent (N)) = N_Subprogram_Declaration - then - -- If the constructor list is empty than we don't have to - -- look for duplicates - we simply create the list and - -- add it. - - if No (Constructor_List (First_Form_Type)) then - Set_Constructor_List - (First_Form_Type, New_Elmt_List (Designator)); - - -- Otherwise, we need to check the constructor hasen't - -- already been added (e.g. a specification and body) and - -- that there isn't a constructor with the same number of - -- type of formals. - - -- NOTE: The Constructor_List is sorted by the number of - -- parameters. - - else - Construct := First_Elmt - (Constructor_List (First_Form_Type)); - - -- Skip over constructors with less than the number of - -- parameters than Designator ??? - - -- Loop through the constructors looking for ones which - -- "match." - - Outter : loop - - -- When we are at the end of the constructor list we - -- know there are no matches, so it is safe to add. - - if No (Construct) then - Append_Elmt - (Designator, - Constructor_List (First_Form_Type)); - exit Outter; - end if; - - -- Loop through the formals and check the formals - -- match on type ??? - - Next_Elmt (Construct); - end loop Outter; - end if; - end if; - end; - end if; - -- The subprogram scope is pushed and popped around the processing of -- the return type for consistency with call above to Process_Formals -- (which itself can call Analyze_Return_Type), and to ensure that any @@ -5511,6 +5516,12 @@ package body Sem_Ch6 is End_Scope; end if; + -- Handle subprogram specification directly referencing an attribute + + if Is_Direct_Attribute_Subp_Spec (N) then + Analyze_Direct_Attribute_Definition (Designator); + end if; + -- Function case if Nkind (N) = N_Function_Specification then diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb index 989e6bf..6032487 100644 --- a/gcc/ada/sem_ch7.adb +++ b/gcc/ada/sem_ch7.adb @@ -835,7 +835,8 @@ package body Sem_Ch7 is -- user entities, as internally generated entities might still need -- to be expanded (e.g. those generated for types). - if Present (Ghost_Config.Ignored_Ghost_Region) + if not CodePeer_Mode + and then Present (Ghost_Config.Ignored_Ghost_Region) and then Comes_From_Source (Body_Id) then Expander_Active := False; @@ -1148,7 +1149,9 @@ package body Sem_Ch7 is end if; end if; - if Present (Ghost_Config.Ignored_Ghost_Region) then + if not CodePeer_Mode and then + Present (Ghost_Config.Ignored_Ghost_Region) + then Expander_Active := Saved_EA; end if; diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index a83ac64..fe7f311 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -136,7 +136,7 @@ package body Sem_Ch8 is -- the order of their corresponding scopes on the scope stack. For -- example, if package P and the enclosing scope both contain entities -- named E, then when compiling the package body the chain for E will - -- hold the global entity first, and the local one (corresponding to + -- hold the global entity first, and the local one (corresponding to -- the current inner scope) next. As a result, name resolution routines -- do not assume any relative ordering of the homonym chains, either -- for scope nesting or to order of appearance of context clauses. @@ -207,7 +207,7 @@ package body Sem_Ch8 is -- a private or incomplete type declaration, or a protected type speci- -- fication) and re-chained when compiling the second view. - -- In the case of operators, we do not make operators on derived types + -- In the case of operators, we do not make operators on derived types -- explicit. As a result, the notation P."+" may denote either a user- -- defined function with name "+", or else an implicit declaration of the -- operator "+" in package P. The resolution of expanded names always @@ -1892,7 +1892,7 @@ package body Sem_Ch8 is Old_S := Find_Renamed_Entity (N, Selector_Name (Nam), New_S); if Old_S = Any_Id then - Error_Msg_N ("no subprogram or entry matches specification", N); + Error_Msg_N ("no subprogram or entry matches specification", N); else if Is_Body then Check_Subtype_Conformant (New_S, Old_S, N); @@ -2073,7 +2073,7 @@ package body Sem_Ch8 is end if; if Old_S = Any_Id then - Error_Msg_N ("no subprogram or entry matches specification", N); + Error_Msg_N ("no subprogram or entry matches specification", N); else if Is_Body then @@ -3848,7 +3848,7 @@ package body Sem_Ch8 is elsif Ekind (Old_S) /= E_Operator then -- If this a defaulted subprogram for a class-wide actual there is - -- no check for mode conformance, given that the signatures don't + -- no check for mode conformance, given that the signatures don't -- match (the source mentions T but the actual mentions T'Class). if CW_Actual then @@ -5213,7 +5213,7 @@ package body Sem_Ch8 is -- An entity in the current scope is not necessarily the first one -- on its homonym chain. Find its predecessor if any, -- If it is an internal entity, it will not be in the visibility - -- chain altogether, and there is nothing to unchain. + -- chain altogether, and there is nothing to unchain. if Id /= Current_Entity (Id) then Prev := Current_Entity (Id); @@ -5248,7 +5248,7 @@ package body Sem_Ch8 is Set_Name_Entity_Id (Chars (Id), Outer); elsif Scope (Prev) /= Scope (Id) then - Set_Homonym (Prev, Outer); + Set_Homonym (Prev, Outer); end if; <<Next_Ent>> @@ -9948,9 +9948,7 @@ package body Sem_Ch8 is and then Scope (S) /= Standard_Standard and then not Is_Child_Unit (S) then - if Nkind (E) not in N_Entity then - return; - end if; + pragma Assert (Nkind (E) in N_Entity); -- Copy categorization flags from Scope (S) to S, this is not done -- when Scope (S) is Standard_Standard since propagation is from diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb index 5a8bd58..4a940e7f 100644 --- a/gcc/ada/sem_disp.adb +++ b/gcc/ada/sem_disp.adb @@ -586,7 +586,6 @@ package body Sem_Disp is Actual : Node_Id; Formal : Entity_Id; Control : Node_Id := Empty; - Func : Entity_Id; Subp_Entity : constant Entity_Id := Entity (Name (N)); Indeterm_Ctrl_Type : Entity_Id := Empty; @@ -1099,55 +1098,6 @@ package body Sem_Disp is Check_Dispatching_Context (N); - elsif Nkind (N) /= N_Function_Call then - - -- The call is not dispatching, so check that there aren't any - -- tag-indeterminate abstract calls left among its actuals. - - Actual := First_Actual (N); - while Present (Actual) loop - if Is_Tag_Indeterminate (Actual) then - - -- Function call case - - if Nkind (Original_Node (Actual)) = N_Function_Call then - Func := Entity (Name (Original_Node (Actual))); - - -- If the actual is an attribute then it can't be abstract - -- (the only current case of a tag-indeterminate attribute - -- is the stream Input attribute). - - elsif Nkind (Original_Node (Actual)) = N_Attribute_Reference - then - Func := Empty; - - -- Ditto if it is an explicit dereference - - elsif Nkind (Original_Node (Actual)) = N_Explicit_Dereference - then - Func := Empty; - - -- Only other possibility is a qualified expression whose - -- constituent expression is itself a call. - - else - Func := - Entity (Name (Original_Node - (Expression (Original_Node (Actual))))); - end if; - - if Present (Func) and then Is_Abstract_Subprogram (Func) then - Error_Msg_N - ("call to abstract function must be dispatching", - Actual); - end if; - end if; - - Next_Actual (Actual); - end loop; - - Check_Dispatching_Context (N); - elsif Nkind (Parent (N)) in N_Subexpr then Check_Dispatching_Context (N); diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 0dc2e4f..0ebf421 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -16449,8 +16449,6 @@ package body Sem_Prag is or else not Is_Access_Type (Entity (Arg)) then Error_Pragma_Arg ("pragma% requires access type", Arg1); - else - Set_Has_Pragma_Controlled (Base_Type (Entity (Arg))); end if; end Controlled; diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 4d46755..bf9d5e1 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -262,9 +262,8 @@ package body Sem_Res is function Operator_Kind (Op_Name : Name_Id; - Is_Binary : Boolean) return Node_Kind; - -- Utility to map the name of an operator into the corresponding Node. Used - -- by other node rewriting procedures. + Is_Binary : Boolean) return N_Op; + -- Map the name of an operator into the corresponding Node_Kind procedure Resolve_Actuals (N : Node_Id; Nam : Entity_Id); -- Resolve actuals of call, and add default expressions for missing ones. @@ -1986,7 +1985,7 @@ package body Sem_Res is function Operator_Kind (Op_Name : Name_Id; - Is_Binary : Boolean) return Node_Kind + Is_Binary : Boolean) return N_Op is Kind : Node_Kind; @@ -10812,7 +10811,12 @@ package body Sem_Res is and then Is_Character_Type (Component_Type (Typ)) then Set_String_Literal_Subtype (Op1, Typ); - Set_String_Literal_Subtype (Op2, Typ); + + -- See Resolve_String_Literal for the asymmetry + + if Ekind (Etype (Op2)) /= E_String_Literal_Subtype then + Set_String_Literal_Subtype (Op2, Typ); + end if; end if; end Resolve_Op_Concat_Rest; @@ -12032,11 +12036,14 @@ package body Sem_Res is begin -- For a string appearing in a concatenation, defer creation of the -- string_literal_subtype until the end of the resolution of the - -- concatenation, because the literal may be constant-folded away. This - -- is a useful optimization for long concatenation expressions. + -- concatenation, because the literal may be constant-folded away. + -- This is a useful optimization for long concatenation expressions, + -- but it cannot be done if the string is the right operand and the + -- left operand may be null, because 4.5.3(5) says that the result is + -- the right operand and, in particular, has its original subtype. -- If the string is an aggregate built for a single character (which - -- happens in a non-static context) or a is null string to which special + -- happens in a non-static context) or is a null string to which special -- checks may apply, we build the subtype. Wide strings must also get a -- string subtype if they come from a one character aggregate. Strings -- generated by attributes might be static, but it is often hard to @@ -12049,6 +12056,11 @@ package body Sem_Res is or else Nkind (Parent (N)) /= N_Op_Concat or else (N /= Left_Opnd (Parent (N)) and then N /= Right_Opnd (Parent (N))) + or else (N = Right_Opnd (Parent (N)) + and then + (Nkind (Left_Opnd (Parent (N))) /= N_String_Literal + or else + String_Length (Strval (Left_Opnd (Parent (N)))) = 0)) or else ((Typ = Standard_Wide_String or else Typ = Standard_Wide_Wide_String) and then Nkind (Original_Node (N)) /= N_String_Literal); diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index a8984c8..cacf29c 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -6332,6 +6332,26 @@ package body Sem_Util is end Conditional_Delay; -------------------------------------- + -- Direct_Attribute_Definition_Name -- + -------------------------------------- + + function Direct_Attribute_Definition_Name + (Prefix : Entity_Id; Att_Name : Name_Id) return Name_Id is + begin + if Nkind (Prefix) = N_Attribute_Reference then + Error_Msg_N ("attribute streams not supported in " + & "direct attribute definitions", + Prefix); + end if; + + pragma Assert (Is_Attribute_Name (Att_Name)); + return New_External_Name + (Related_Id => Chars (Prefix), + Suffix => "_" & Get_Name_String (Att_Name) & "_Att", + Prefix => 'D'); + end Direct_Attribute_Definition_Name; + + -------------------------------------- -- Copy_Assertion_Policy_Attributes -- -------------------------------------- @@ -6832,30 +6852,6 @@ package body Sem_Util is return Is_Class_Wide_Type (Typ) or else Needs_Finalization (Typ); end CW_Or_Needs_Finalization; - ------------------------- - -- Default_Constructor -- - ------------------------- - - function Default_Constructor (Typ : Entity_Id) return Entity_Id is - Construct : Elmt_Id; - begin - pragma Assert (Is_Type (Typ)); - if No (Constructor_Name (Typ)) or else No (Constructor_List (Typ)) then - return Empty; - end if; - - Construct := First_Elmt (Constructor_List (Typ)); - while Present (Construct) loop - if Parameter_Count (Elists.Node (Construct)) = 1 then - return Elists.Node (Construct); - end if; - - Next_Elmt (Construct); - end loop; - - return Empty; - end Default_Constructor; - --------------------- -- Defining_Entity -- --------------------- @@ -11850,6 +11846,35 @@ package body Sem_Util is (First_Discriminant (Typ))); end Has_Defaulted_Discriminants; + ----------------------------- + -- Has_Default_Constructor -- + ----------------------------- + + function Has_Default_Constructor (Typ : Entity_Id) return Boolean is + Cursor : Entity_Id; + begin + pragma Assert (Is_Type (Typ)); + if not Needs_Construction (Typ) then + return False; + end if; + + -- Iterate through all homonyms to find the default constructor + + Cursor := Get_Name_Entity_Id + (Direct_Attribute_Definition_Name (Typ, Name_Constructor)); + while Present (Cursor) loop + if Is_Constructor_Procedure (Cursor) + and then No (Next_Formal (First_Formal (Cursor))) + then + return True; + end if; + + Cursor := Homonym (Cursor); + end loop; + + return False; + end Has_Default_Constructor; + ------------------- -- Has_Denormals -- ------------------- @@ -16249,6 +16274,17 @@ package body Sem_Util is and then Attribute_Name (N) = Name_Result; end Is_Attribute_Result; + ----------------------------------- + -- Is_Direct_Attribute_Subp_Spec -- + ----------------------------------- + + function Is_Direct_Attribute_Subp_Spec (N : Node_Id) return Boolean is + begin + return Nkind (N) in N_Subprogram_Specification + and then Nkind (Defining_Unit_Name (Original_Node (N))) + = N_Attribute_Reference; + end Is_Direct_Attribute_Subp_Spec; + ------------------------- -- Is_Attribute_Update -- ------------------------- @@ -16684,6 +16720,28 @@ package body Sem_Util is end if; end Is_Constant_Bound; + ------------------------------ + -- Is_Constructor_Procedure -- + ------------------------------ + + function Is_Constructor_Procedure (Subp : Entity_Id) return Boolean is + First_Param : Entity_Id; + begin + if not (Present (First_Formal (Subp)) + and then Ekind (First_Formal (Subp)) = E_In_Out_Parameter + and then Is_Direct_Attribute_Subp_Spec (Parent (Subp)) + and then Attribute_Name (Defining_Unit_Name + (Original_Node (Parent (Subp)))) + = Name_Constructor) + then + return False; + end if; + + First_Param := Implementation_Base_Type (Etype (First_Formal (Subp))); + return Scope (Subp) = Scope (First_Param) + and then Needs_Construction (First_Param); + end Is_Constructor_Procedure; + --------------------------- -- Is_Container_Element -- --------------------------- @@ -24817,10 +24875,20 @@ package body Sem_Util is -- Scalar_Range if Is_Discrete_Type (Id) then + + -- The scalar range of the source entity had a parent, so the + -- scalar range of the newly created entity should also have a + -- parent, so that the AST structure is the same. + + pragma Assert (Present (Parent (Scalar_Range (Id)))); + Set_Scalar_Range (Id, Node_Id ( Copy_Field_With_Replacement (Field => Union_Id (Scalar_Range (Id)), Semantic => True))); + + pragma Assert (No (Parent (Scalar_Range (Id)))); + Set_Parent (Scalar_Range (Id), Id); end if; -- Scope @@ -26669,24 +26737,6 @@ package body Sem_Util is return Empty; end Param_Entity; - --------------------- - -- Parameter_Count -- - --------------------- - - function Parameter_Count (Subp : Entity_Id) return Nat is - Result : Nat := 0; - Param : Entity_Id; - begin - Param := First_Entity (Subp); - while Present (Param) loop - Result := Result + 1; - - Param := Next_Entity (Param); - end loop; - - return Result; - end Parameter_Count; - ---------------------- -- Policy_In_Effect -- ---------------------- @@ -27097,6 +27147,11 @@ package body Sem_Util is -- the case where Ent is a child unit. This procedure generates an -- appropriate cross-reference entry. E is the corresponding entity. + procedure Get_Attribute_Reference_Name_String (N : Node_Id); + -- This procedure append to the Global_Name_Buffer the decoded string + -- name of the attribute reference N, including apostrophes and multiple + -- prefixes. + ------------------------- -- Generate_Parent_Ref -- ------------------------- @@ -27118,6 +27173,21 @@ package body Sem_Util is end if; end Generate_Parent_Ref; + ----------------------------------------- + -- Get_Attribute_Reference_Name_String -- + ----------------------------------------- + + procedure Get_Attribute_Reference_Name_String (N : Node_Id) is + begin + if Nkind (N) /= N_Attribute_Reference then + Get_Decoded_Name_String (Chars (N)); + else + Get_Attribute_Reference_Name_String (Prefix (N)); + Append (Global_Name_Buffer, '''); + Get_Decoded_Name_String (Attribute_Name (N)); + end if; + end Get_Attribute_Reference_Name_String; + -- Start of processing for Process_End_Label begin @@ -27198,9 +27268,12 @@ package body Sem_Util is -- If the end label is not for the given entity, then either we have -- some previous error, or this is a generic instantiation for which -- we do not need to make a cross-reference in this case anyway. In - -- either case we simply ignore the call. + -- either case we simply ignore the call. Matching label for direct + -- attribute definitions are checked elsewhere. - if Chars (Ent) /= Chars (Endl) then + if Nkind (Endl) /= N_Attribute_Reference + and then Chars (Ent) /= Chars (Endl) + then return; end if; @@ -27227,7 +27300,7 @@ package body Sem_Util is -- mean the semicolon immediately following the label). This is -- done for the sake of the 'e' or 't' entry generated below. - Get_Decoded_Name_String (Chars (Endl)); + Get_Attribute_Reference_Name_String (Endl); Set_Sloc (Endl, Sloc (Endl) + Source_Ptr (Name_Len)); end if; diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index ee9ecd2..71889b2 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -569,6 +569,10 @@ package Sem_Util is -- of Old_Ent is set and Old_Ent has not yet been Frozen (i.e. Is_Frozen is -- False). + function Direct_Attribute_Definition_Name + (Prefix : Entity_Id; Att_Name : Name_Id) return Name_Id; + -- Returns the name used for entities of direct attribute definitions. + procedure Copy_Assertion_Policy_Attributes (New_Prag, Old_Prag : Node_Id); -- Copy Is_Checked, Is_Ignored and Ghost_Assertion_Level attributes from -- Old_Node. @@ -674,10 +678,6 @@ package Sem_Util is -- as Needs_Finalization except with pragma Restrictions (No_Finalization), -- in which case we know that class-wide objects do not need finalization. - function Default_Constructor (Typ : Entity_Id) return Entity_Id; - -- Determine the default constructor (e.g. the constructor with only one - -- formal parameter) for a given type Typ. - function Defining_Entity (N : Node_Id) return Entity_Id; -- Given a declaration N, returns the associated defining entity. If the -- declaration has a specification, the entity is obtained from the @@ -1407,6 +1407,9 @@ package Sem_Util is function Has_Defaulted_Discriminants (Typ : Entity_Id) return Boolean; -- Simple predicate to test for defaulted discriminants + function Has_Default_Constructor (Typ : Entity_Id) return Boolean; + -- Determine whether Typ has a constructor with only one formal parameter. + function Has_Denormals (E : Entity_Id) return Boolean; -- Determines if the floating-point type E supports denormal numbers. -- Returns False if E is not a floating-point type. @@ -1880,6 +1883,10 @@ package Sem_Util is function Is_Attribute_Result (N : Node_Id) return Boolean; -- Determine whether node N denotes attribute 'Result + function Is_Direct_Attribute_Subp_Spec (N : Node_Id) return Boolean; + -- Determine whether N denotes a direct attribute definition subprogram + -- specification node. + function Is_Attribute_Update (N : Node_Id) return Boolean; -- Determine whether node N denotes attribute 'Update @@ -1914,6 +1921,10 @@ package Sem_Util is -- enumeration literal, or an expression composed of constant-bound -- subexpressions which are evaluated by means of standard operators. + function Is_Constructor_Procedure (Subp : Entity_Id) return Boolean; + -- Returns True if Subp's name directly references an attribute, has a + -- first in out formal that needs construction within the same scope. + function Is_Container_Element (Exp : Node_Id) return Boolean; -- This routine recognizes expressions that denote an element of one of -- the predefined containers, when the source only contains an indexing @@ -2973,9 +2984,6 @@ package Sem_Util is -- WARNING: this routine should be used in debugging scenarios such as -- tracking down undefined symbols as it is fairly low level. - function Parameter_Count (Subp : Entity_Id) return Nat; - -- Return the number of parameters for a given subprogram Subp. - function Param_Entity (N : Node_Id) return Entity_Id; -- Given an expression N, determines if the expression is a reference -- to a formal (of a subprogram or entry), and if so returns the Id diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index 2c15b80..8a35fdc 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -690,7 +690,6 @@ package Sinfo is -- Do_Discriminant_Check -- Do_Length_Check - -- Do_Storage_Check -- These flags are used in some specific cases by the front end, either -- during semantic analysis or during expansion, and cannot be expected @@ -1003,9 +1002,10 @@ package Sinfo is -- to the defining entity for the corresponding body (NOT the node for -- the body itself). - -- Corresponding_Entry_Body + -- Corresponding_Entry_Body -- Defined in N_Subprogram_Body. Set for subprogram bodies that implement -- a protected type entry; points to the body for the entry. + -- Used by codepeer. -- Corresponding_Formal_Spec -- This field is set in subprogram renaming declarations, where it points @@ -1057,13 +1057,6 @@ package Sinfo is -- This field is present in an N_Variant node, It references the entity -- for the discriminant checking function for the variant. - -- Default_Expression - -- This field is Empty if there is no default expression. If there is a - -- simple default expression (one with no side effects), then this field - -- simply contains a copy of the Expression field (both point to the tree - -- for the default expression). Default_Expression is used for - -- conformance checking. - -- Default_Storage_Pool -- This field is present in N_Compilation_Unit_Aux nodes. It is set to a -- copy of Opt.Default_Pool at the end of the compilation unit. See @@ -1151,14 +1144,6 @@ package Sinfo is -- listed above (e.g. in a return statement), an additional type -- conversion node is introduced to represent the required check. - -- Do_Storage_Check - -- This flag is set in an N_Allocator node to indicate that a storage - -- check is required for the allocation, or in an N_Subprogram_Body node - -- to indicate that a stack check is required in the subprogram prologue. - -- The N_Allocator case is handled by the routine that expands the call - -- to the runtime routine. The N_Subprogram_Body case is handled by the - -- backend, and all the semantics does is set the flag. - -- Elaborate_Present -- This flag is set in the N_With_Clause node to indicate that pragma -- Elaborate pragma appears for the with'ed units. @@ -1188,12 +1173,6 @@ package Sinfo is -- need for this field, so in the tree passed to Gigi, this field is -- always set to No_List. - -- Enclosing_Variant - -- This field is present in the N_Variant node and identifies the Node_Id - -- corresponding to the immediately enclosing variant when the variant is - -- nested, and N_Empty otherwise. Set during semantic processing of the - -- variant part of a record type. - -- Entity -- Appears in all direct names (identifiers, character literals, and -- operator symbols), as well as expanded names, and attributes that @@ -1394,14 +1373,6 @@ package Sinfo is -- Generic_Parent_Type is also used in an instance to determine whether a -- private operation overrides an inherited one. - -- Handler_List_Entry - -- This field is present in N_Object_Declaration nodes. It is set only - -- for the Handler_Record entry generated for an exception in zero cost - -- exception handling mode. It references the corresponding item in the - -- handler list, and is used to delete this entry if the corresponding - -- handler is deleted during optimization. For further details on why - -- this is required, see Exp_Ch11.Remove_Handler_Entries. - -- Has_Dereference_Action -- This flag is present in N_Explicit_Dereference nodes. It is set to -- indicate that the expansion has aready produced a call to primitive @@ -1884,11 +1855,6 @@ package Sinfo is -- the generic unit on the actual parameters done in the outermost scope -- where it would be legal to declare an identical named instantiation. - -- Is_Subprogram_Descriptor - -- Present in N_Object_Declaration, and set only for the object - -- declaration generated for a subprogram descriptor in fast exception - -- mode. See Exp_Ch11 for details of use. - -- Is_Task_Allocation_Block -- A flag set in a Block_Statement node to indicate that it is the -- expansion of a task allocator, or the allocator of an object @@ -2237,14 +2203,6 @@ package Sinfo is -- to indicate that a use is redundant (and therefore need not be undone -- on scope exit). - -- Renaming_Exception - -- Present in N_Exception_Declaration node. Used to point back to the - -- exception renaming for an exception declared within a subprogram. - -- What happens is that an exception declared in a subprogram is moved - -- to the library level with a unique name, and the original exception - -- becomes a renaming. This link from the library level exception to the - -- renaming declaration allows registering of the proper exception name. - -- Return_Statement_Entity -- Present in N_Simple_Return_Statement and N_Extended_Return_Statement. -- Points to an E_Return_Statement representing the return statement. @@ -3020,14 +2978,12 @@ package Sinfo is -- Null_Exclusion_Present -- Object_Definition subtype indic./array type def./access def. -- Expression (set to Empty if not present) - -- Handler_List_Entry -- Corresponding_Generic_Association -- More_Ids (set to False if no more identifiers in list) -- Prev_Ids (set to False if no previous identifiers in list) -- No_Initialization -- Assignment_OK -- Exception_Junk - -- Is_Subprogram_Descriptor -- Has_Init_Expression -- Suppress_Assignment_Checks @@ -3632,7 +3588,6 @@ package Sinfo is -- Sloc points to WHEN -- Discrete_Choices -- Component_List - -- Enclosing_Variant -- Present_Expr -- Dcheck_Function -- Has_SP_Choice @@ -4853,7 +4808,6 @@ package Sinfo is -- Null_Exclusion_Present -- No_Initialization -- Is_Static_Coextension - -- Do_Storage_Check -- Is_Dynamic_Coextension -- plus fields for expression @@ -5505,10 +5459,9 @@ package Sinfo is -- Out_Present -- Null_Exclusion_Present -- Parameter_Type subtype mark or access definition - -- Expression (set to Empty if no default expression present) + -- Expression (set to Empty if no default expression) -- More_Ids (set to False if no more identifiers in list) -- Prev_Ids (set to False if no previous identifiers in list) - -- Default_Expression --------------- -- 6.1 Mode -- @@ -5541,7 +5494,6 @@ package Sinfo is -- At_End_Proc (set to Empty if no clean up procedure) -- Acts_As_Spec -- Bad_Is_Detected used only by parser - -- Do_Storage_Check -- Has_Relative_Deadline_Pragma -- Is_Entry_Barrier_Function -- Is_Protected_Subprogram_Body @@ -6887,11 +6839,16 @@ package Sinfo is -- N_Exception_Declaration -- Sloc points to EXCEPTION -- Defining_Identifier - -- Expression - -- Renaming_Exception + -- Expression (see below) -- More_Ids (set to False if no more identifiers in list) -- Prev_Ids (set to False if no previous identifiers in list) + -- Expression is not present in the syntax; it is set during expansion. + -- An exception_declaration is treated by the back end like an object of + -- type Standard.Exception_Type, and Expression is the initial value. + -- Expression is a syntactic field to match the Expression fields of + -- other node kinds. + ------------------------------------------ -- 11.2 Handled Sequence Of Statements -- ------------------------------------------ @@ -7236,7 +7193,7 @@ package Sinfo is -- Null_Exclusion_Present (set to False if not present) -- Subtype_Mark (set to Empty if not present) -- Access_Definition (set to Empty if not present) - -- Default_Expression (set to Empty if no default expression) + -- Expression (set to Empty if no default expression) -- More_Ids (set to False if no more identifiers in list) -- Prev_Ids (set to False if no previous identifiers in list) @@ -7987,6 +7944,9 @@ package Sinfo is -- N_Compound_Statement -- Actions + -- Note that N_Compound_Statement is unrelated to the Ada syntax rule + -- for compound_statement. + -------------- -- Contract -- -------------- diff --git a/gcc/ada/snames.adb-tmpl b/gcc/ada/snames.adb-tmpl index fcfd390..b5f53cd 100644 --- a/gcc/ada/snames.adb-tmpl +++ b/gcc/ada/snames.adb-tmpl @@ -412,6 +412,15 @@ package body Snames is end if; end Is_Convention_Name; + ----------------------------------------- + -- Is_Direct_Attribute_Definition_Name -- + ----------------------------------------- + + function Is_Direct_Attribute_Definition_Name (N : Name_Id) return Boolean is + begin + return Is_Attribute_Name (N) and then N = Name_Constructor; + end Is_Direct_Attribute_Definition_Name; + ------------------------------ -- Is_Entity_Attribute_Name -- ------------------------------ diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl index d6fe60b..cb07f97 100644 --- a/gcc/ada/snames.ads-tmpl +++ b/gcc/ada/snames.ads-tmpl @@ -147,7 +147,6 @@ package Snames is -- Names of aspects for which there are no matching pragmas or attributes -- so that they need to be included for aspect specification use. - Name_Constructor : constant Name_Id := N + $; Name_Default_Value : constant Name_Id := N + $; Name_Default_Component_Value : constant Name_Id := N + $; Name_Designated_Storage_Model : constant Name_Id := N + $; @@ -956,6 +955,7 @@ package Snames is Name_Component_Size : constant Name_Id := N + $; Name_Compose : constant Name_Id := N + $; Name_Constrained : constant Name_Id := N + $; + Name_Constructor : constant Name_Id := N + $; Name_Count : constant Name_Id := N + $; Name_Default_Bit_Order : constant Name_Id := N + $; -- GNAT Name_Default_Scalar_Storage_Order : constant Name_Id := N + $; -- GNAT @@ -1500,6 +1500,7 @@ package Snames is Attribute_Component_Size, Attribute_Compose, Attribute_Constrained, + Attribute_Constructor, Attribute_Count, Attribute_Default_Bit_Order, Attribute_Default_Scalar_Storage_Order, @@ -2077,6 +2078,10 @@ package Snames is -- mode. This is the mechanism for considering this pragma illegal in -- normal GNAT programs. + function Is_Direct_Attribute_Definition_Name (N : Name_Id) return Boolean; + -- Test to see if the name N is the name of a recognized attribute and is + -- allowed to be directly referenced in subprogram specification. + function Is_Entity_Attribute_Name (N : Name_Id) return Boolean; -- Test to see if the name N is the name of a recognized entity attribute, -- i.e. an attribute reference that returns an entity. diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb index f5caa3d..8c49864 100644 --- a/gcc/ada/sprint.adb +++ b/gcc/ada/sprint.adb @@ -1963,9 +1963,9 @@ package body Sprint is Sprint_Node (Access_Definition (Node)); end if; - if Present (Default_Expression (Node)) then + if Present (Expression (Node)) then Write_Str (" := "); - Sprint_Node (Default_Expression (Node)); + Sprint_Node (Expression (Node)); end if; Write_Char (';'); diff --git a/gcc/ada/style.adb b/gcc/ada/style.adb index 6e5688d..56d1060 100644 --- a/gcc/ada/style.adb +++ b/gcc/ada/style.adb @@ -345,12 +345,14 @@ package body Style is begin if Style_Check_Xtra_Parens_Precedence and then - Paren_Count (N) > - (if Nkind (N) in N_Case_Expression - | N_Expression_With_Actions - | N_If_Expression - | N_Quantified_Expression - | N_Raise_Expression + Paren_Count (Original_Node (N)) > + (if Nkind (Original_Node (N)) in N_Case_Expression + | N_Expression_With_Actions + | N_If_Expression + | N_Quantified_Expression + | N_Raise_Expression + | N_In + | N_Not_In then 1 else 0) then diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb index fbad71a..9d78987 100644 --- a/gcc/ada/treepr.adb +++ b/gcc/ada/treepr.adb @@ -338,6 +338,8 @@ package body Treepr is return "Is_Elaboration_Checks_OK_Id"; when F_Is_Elaboration_Warnings_OK_Id => return "Is_Elaboration_Warnings_OK_Id"; + when F_Is_IEEE_Extended_Precision => + return "Is_IEEE_Extended_Precision"; when F_Is_RACW_Stub_Type => return "Is_RACW_Stub_Type"; when F_LSP_Subprogram => diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def index a70375c05..083515d 100644 --- a/gcc/config/aarch64/aarch64-option-extensions.def +++ b/gcc/config/aarch64/aarch64-option-extensions.def @@ -155,6 +155,12 @@ AARCH64_OPT_EXTENSION("fp16fml", F16FML, (), (F16), (), "asimdfhm") AARCH64_FMV_FEATURE("fp16fml", FP16FML, (F16FML)) +AARCH64_FMV_FEATURE("dit", DIT, ()) + +AARCH64_FMV_FEATURE("dpb", DPB, ()) + +AARCH64_FMV_FEATURE("dpb2", DPB2, ()) + AARCH64_OPT_FMV_EXTENSION("jscvt", JSCVT, (FP), (), (), "jscvt") AARCH64_OPT_FMV_EXTENSION("fcma", FCMA, (SIMD), (), (), "fcma") @@ -209,13 +215,15 @@ AARCH64_OPT_EXTENSION("sve2p1", SVE2p1, (SVE2), (), (), "sve2p1") AARCH64_OPT_FMV_EXTENSION("sme", SME, (BF16, FCMA, F16, F16FML), (), (), "sme") -AARCH64_OPT_EXTENSION("memtag", MEMTAG, (), (), (), "") +AARCH64_OPT_FMV_EXTENSION("memtag", MEMTAG, (), (), (), "") AARCH64_OPT_FMV_EXTENSION("sb", SB, (), (), (), "sb") AARCH64_OPT_EXTENSION("predres", PREDRES, (), (), (), "") -AARCH64_OPT_EXTENSION("ssbs", SSBS, (), (), (), "ssbs") +AARCH64_OPT_FMV_EXTENSION("ssbs", SSBS, (), (), (), "ssbs") + +AARCH64_FMV_FEATURE("bti", BTI, ()) AARCH64_OPT_EXTENSION("profile", PROFILE, (), (), (), "") diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 6f6dea6..74e2f20 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -20380,6 +20380,8 @@ typedef struct /* The "rdma" alias uses a different FEAT_NAME to avoid a duplicate feature_deps name. */ #define FEAT_RDMA FEAT_RDM +#define FEAT_SSBS FEAT_SSBS2 +#define FEAT_MEMTAG FEAT_MEMTAG2 /* FMV features are listed in priority order, to make it easier to sort target strings. */ diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md index a53b2ba..53e0c83 100644 --- a/gcc/config/arc/simdext.md +++ b/gcc/config/arc/simdext.md @@ -1438,11 +1438,15 @@ "reload_completed && GET_CODE (operands[1]) == CONST_VECTOR" [(set (match_dup 0) (match_dup 2))] { - HOST_WIDE_INT intval = INTVAL (XVECEXP (operands[1], 0, 1)) << 16; - intval |= INTVAL (XVECEXP (operands[1], 0, 0)) & 0xFFFF; - - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); - operands[2] = GEN_INT (trunc_int_for_mode (intval, SImode)); + int hi = TARGET_BIG_ENDIAN ? 0 : 1; + int lo = TARGET_BIG_ENDIAN ? 1 : 0; + HOST_WIDE_INT hi_val = INTVAL (XVECEXP (operands[1], 0, hi)); + HOST_WIDE_INT lo_val = INTVAL (XVECEXP (operands[1], 0, lo)); + hi_val = zext_hwi (hi_val, 16); + lo_val = zext_hwi (lo_val, 16); + HOST_WIDE_INT intval = lo_val | (hi_val << 16); + operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); + operands[2] = GEN_INT (trunc_int_for_mode (intval, SImode)); } [(set_attr "type" "move,move,load,store") (set_attr "predicable" "yes,yes,no,no") diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index a1f1b26..c131f7c 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -9995,6 +9995,754 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp, return true; } +/* Fully unroll memmove of known size with up to 8 registers. */ + +static bool +ix86_expand_unroll_movmem (rtx dst, rtx src, rtx destreg, rtx srcreg, + unsigned HOST_WIDE_INT count, + machine_mode mode) +{ + /* If 8 registers registers can cover all memory, load them into + registers and store them together to avoid possible address + overlap between source and destination. */ + unsigned HOST_WIDE_INT moves = count / GET_MODE_SIZE (mode); + if (moves == 0) + { + mode = smallest_int_mode_for_size + (count * BITS_PER_UNIT).require (); + if (count == GET_MODE_SIZE (mode)) + moves = 1; + else + { + /* Reduce the smallest move size by half so that MOVES == 1. */ + mode = smallest_int_mode_for_size + (GET_MODE_BITSIZE (mode) / 2).require (); + moves = count / GET_MODE_SIZE (mode); + gcc_assert (moves == 1); + } + } + else if (moves > 8) + return false; + + unsigned int i; + rtx tmp[9]; + + for (i = 0; i < moves; i++) + tmp[i] = gen_reg_rtx (mode); + + rtx srcmem = change_address (src, mode, srcreg); + for (i = 0; i < moves; i++) + { + emit_move_insn (tmp[i], srcmem); + srcmem = offset_address (srcmem, + GEN_INT (GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + } + + unsigned int epilogue_size = count & (GET_MODE_SIZE (mode) - 1); + machine_mode epilogue_mode = VOIDmode; + if (epilogue_size) + { + /* Handle the remaining bytes with overlapping move. */ + epilogue_mode = smallest_int_mode_for_size + (epilogue_size * BITS_PER_UNIT).require (); + tmp[8] = gen_reg_rtx (epilogue_mode); + srcmem = adjust_address (srcmem, epilogue_mode, 0); + srcmem = offset_address (srcmem, GEN_INT (epilogue_size), 1); + srcmem = offset_address (srcmem, + GEN_INT (-GET_MODE_SIZE (epilogue_mode)), + GET_MODE_SIZE (epilogue_mode)); + emit_move_insn (tmp[8], srcmem); + } + + rtx destmem = change_address (dst, mode, destreg); + for (i = 0; i < moves; i++) + { + emit_move_insn (destmem, tmp[i]); + destmem = offset_address (destmem, + GEN_INT (GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + } + + if (epilogue_size) + { + /* Use overlapping move. */ + destmem = adjust_address (destmem, epilogue_mode, 0); + destmem = offset_address (destmem, GEN_INT (epilogue_size), 1); + destmem = offset_address (destmem, + GEN_INT (-GET_MODE_SIZE (epilogue_mode)), + GET_MODE_SIZE (epilogue_mode)); + emit_move_insn (destmem, tmp[8]); + } + + return true; +} + +/* Expand memmove of size with MOVES * mode size and MOVES <= 4. If + FORWARD is true, copy forward. Otherwise copy backward. */ + +static void +ix86_expand_n_move_movmem (rtx destmem, rtx srcmem, machine_mode mode, + unsigned int moves, bool forward) +{ + gcc_assert (moves <= 4); + + unsigned int i; + rtx tmp[8]; + + for (i = 0; i < moves; i++) + tmp[i] = gen_reg_rtx (mode); + + rtx step; + if (forward) + step = GEN_INT (GET_MODE_SIZE (mode)); + else + step = GEN_INT (-GET_MODE_SIZE (mode)); + + /* Load MOVES. */ + for (i = 0; i < moves - 1; i++) + { + emit_move_insn (tmp[i], srcmem); + srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode)); + } + emit_move_insn (tmp[i], srcmem); + + /* Store MOVES. */ + for (i = 0; i < moves - 1; i++) + { + emit_move_insn (destmem, tmp[i]); + destmem = offset_address (destmem, step, GET_MODE_SIZE (mode)); + } + emit_move_insn (destmem, tmp[i]); +} + +/* Load MOVES of mode size into REGS. If LAST is true, load the + last MOVES. Otherwise, load the first MOVES. */ + +static void +ix86_expand_load_movmem (rtx src, rtx srcreg, rtx count_exp, + machine_mode mode, unsigned int moves, + rtx regs[], bool last) +{ + unsigned int i; + + for (i = 0; i < moves; i++) + regs[i] = gen_reg_rtx (mode); + + rtx srcmem = change_address (src, mode, srcreg); + rtx step; + if (last) + { + srcmem = offset_address (srcmem, count_exp, 1); + step = GEN_INT (-GET_MODE_SIZE (mode)); + srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode)); + } + else + step = GEN_INT (GET_MODE_SIZE (mode)); + + for (i = 0; i < moves - 1; i++) + { + emit_move_insn (regs[i], srcmem); + srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode)); + } + emit_move_insn (regs[i], srcmem); +} + +/* Store MOVES of mode size into REGS. If LAST is true, store the + last MOVES. Otherwise, store the first MOVES. */ + +static void +ix86_expand_store_movmem (rtx dst, rtx destreg, rtx count_exp, + machine_mode mode, unsigned int moves, + rtx regs[], bool last) +{ + unsigned int i; + + rtx destmem = change_address (dst, mode, destreg); + rtx step; + if (last) + { + destmem = offset_address (destmem, count_exp, 1); + step = GEN_INT (-GET_MODE_SIZE (mode)); + destmem = offset_address (destmem, step, GET_MODE_SIZE (mode)); + } + else + step = GEN_INT (GET_MODE_SIZE (mode)); + + for (i = 0; i < moves - 1; i++) + { + emit_move_insn (destmem, regs[i]); + destmem = offset_address (destmem, step, GET_MODE_SIZE (mode)); + } + emit_move_insn (destmem, regs[i]); +} + +/* Expand memmove of size between (MOVES / 2) * mode size and + MOVES * mode size with overlapping load and store. MOVES is even. + MOVES >= 2 and MOVES <= 8. */ + +static void +ix86_expand_n_overlapping_move_movmem (rtx dst, rtx src, rtx destreg, + rtx srcreg, rtx count_exp, + machine_mode mode, + unsigned int moves) +{ + gcc_assert (moves >= 2 && moves <= 8 && (moves & 1) == 0); + + unsigned int half_moves = moves / 2; + unsigned int i, j; + rtx tmp[8]; + + for (i = 0; i < moves; i++) + tmp[i] = gen_reg_rtx (mode); + + rtx base_srcmem = change_address (src, mode, srcreg); + + /* Load the first half. */ + rtx srcmem = base_srcmem; + for (i = 0; i < half_moves - 1; i++) + { + emit_move_insn (tmp[i], srcmem); + srcmem = offset_address (srcmem, + GEN_INT (GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + } + emit_move_insn (tmp[i], srcmem); + + /* Load the second half. */ + srcmem = offset_address (base_srcmem, count_exp, 1); + srcmem = offset_address (srcmem, + GEN_INT (-GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + for (j = half_moves, i = 0; i < half_moves - 1; i++, j++) + { + emit_move_insn (tmp[j], srcmem); + srcmem = offset_address (srcmem, + GEN_INT (-GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + } + emit_move_insn (tmp[j], srcmem); + + rtx base_destmem = change_address (dst, mode, destreg); + + /* Store the first half. */ + rtx destmem = base_destmem; + for (i = 0; i < half_moves - 1; i++) + { + emit_move_insn (destmem, tmp[i]); + destmem = offset_address (destmem, + GEN_INT (GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + } + emit_move_insn (destmem, tmp[i]); + + /* Store the second half. */ + destmem = offset_address (base_destmem, count_exp, 1); + destmem = offset_address (destmem, GEN_INT (-GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + for (j = half_moves, i = 0; i < half_moves - 1; i++, j++) + { + emit_move_insn (destmem, tmp[j]); + destmem = offset_address (destmem, GEN_INT (-GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + } + emit_move_insn (destmem, tmp[j]); +} + +/* Expand memmove of size < mode size which is <= 64. */ + +static void +ix86_expand_less_move_movmem (rtx dst, rtx src, rtx destreg, + rtx srcreg, rtx count_exp, + unsigned HOST_WIDE_INT min_size, + machine_mode mode, + rtx_code_label *done_label) +{ + bool skip = false; + machine_mode count_mode = counter_mode (count_exp); + + rtx_code_label *between_32_63_label + = GET_MODE_SIZE (mode) > 32 ? gen_label_rtx () : nullptr; + /* Jump to BETWEEN_32_64_LABEL if size >= 32 and size < 64. */ + if (between_32_63_label) + { + if (min_size && min_size >= 32) + { + emit_jump_insn (gen_jump (between_32_63_label)); + emit_barrier (); + skip = true; + } + else + emit_cmp_and_jump_insns (count_exp, GEN_INT (32), GEU, + nullptr, count_mode, 1, + between_32_63_label); + } + + rtx_code_label *between_16_31_label + = (!skip && GET_MODE_SIZE (mode) > 16) ? gen_label_rtx () : nullptr; + /* Jump to BETWEEN_16_31_LABEL if size >= 16 and size < 31. */ + if (between_16_31_label) + { + if (min_size && min_size >= 16) + { + emit_jump_insn (gen_jump (between_16_31_label)); + emit_barrier (); + skip = true; + } + else + emit_cmp_and_jump_insns (count_exp, GEN_INT (16), GEU, + nullptr, count_mode, 1, + between_16_31_label); + } + + rtx_code_label *between_8_15_label + = (!skip && GET_MODE_SIZE (mode) > 8) ? gen_label_rtx () : nullptr; + /* Jump to BETWEEN_8_15_LABEL if size >= 8 and size < 15. */ + if (between_8_15_label) + { + if (min_size && min_size >= 8) + { + emit_jump_insn (gen_jump (between_8_15_label)); + emit_barrier (); + skip = true; + } + else + emit_cmp_and_jump_insns (count_exp, GEN_INT (8), GEU, + nullptr, count_mode, 1, + between_8_15_label); + } + + rtx_code_label *between_4_7_label + = (!skip && GET_MODE_SIZE (mode) > 4) ? gen_label_rtx () : nullptr; + /* Jump to BETWEEN_4_7_LABEL if size >= 4 and size < 7. */ + if (between_4_7_label) + { + if (min_size && min_size >= 4) + { + emit_jump_insn (gen_jump (between_4_7_label)); + emit_barrier (); + skip = true; + } + else + emit_cmp_and_jump_insns (count_exp, GEN_INT (4), GEU, + nullptr, count_mode, 1, + between_4_7_label); + } + + rtx_code_label *between_2_3_label + = (!skip && GET_MODE_SIZE (mode) > 2) ? gen_label_rtx () : nullptr; + /* Jump to BETWEEN_2_3_LABEL if size >= 2 and size < 3. */ + if (between_2_3_label) + { + if (min_size && min_size >= 2) + { + emit_jump_insn (gen_jump (between_2_3_label)); + emit_barrier (); + skip = true; + } + else + emit_cmp_and_jump_insns (count_exp, GEN_INT (1), GT, + nullptr, count_mode, 1, + between_2_3_label); + } + + if (!skip) + { + rtx_code_label *zero_label + = min_size == 0 ? gen_label_rtx () : nullptr; + /* Skip if size == 0. */ + if (zero_label) + emit_cmp_and_jump_insns (count_exp, GEN_INT (1), LT, + nullptr, count_mode, 1, + zero_label, + profile_probability::unlikely ()); + + /* Move 1 byte. */ + rtx tmp0 = gen_reg_rtx (QImode); + rtx srcmem = change_address (src, QImode, srcreg); + emit_move_insn (tmp0, srcmem); + rtx destmem = change_address (dst, QImode, destreg); + emit_move_insn (destmem, tmp0); + + if (zero_label) + emit_label (zero_label); + + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (between_32_63_label) + { + emit_label (between_32_63_label); + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg, + count_exp, OImode, 2); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (between_16_31_label) + { + emit_label (between_16_31_label); + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg, + count_exp, TImode, 2); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (between_8_15_label) + { + emit_label (between_8_15_label); + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg, + count_exp, DImode, 2); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (between_4_7_label) + { + emit_label (between_4_7_label); + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg, + count_exp, SImode, 2); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (between_2_3_label) + { + emit_label (between_2_3_label); + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg, + count_exp, HImode, 2); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } +} + +/* Expand movmem with overlapping unaligned loads and stores: + 1. Load all sources into registers and store them together to avoid + possible address overlap between source and destination. + 2. For known size, first try to fully unroll with 8 registers. + 3. For size <= 2 * MOVE_MAX, load all sources into 2 registers first + and then store them together. + 4. For size > 2 * MOVE_MAX and size <= 4 * MOVE_MAX, load all sources + into 4 registers first and then store them together. + 5. For size > 4 * MOVE_MAX and size <= 8 * MOVE_MAX, load all sources + into 8 registers first and then store them together. + 6. For size > 8 * MOVE_MAX, + a. If address of destination > address of source, copy backward + with a 4 * MOVE_MAX loop with unaligned loads and stores. Load + the first 4 * MOVE_MAX into 4 registers before the loop and + store them after the loop to support overlapping addresses. + b. Otherwise, copy forward with a 4 * MOVE_MAX loop with unaligned + loads and stores. Load the last 4 * MOVE_MAX into 4 registers + before the loop and store them after the loop to support + overlapping addresses. + */ + +bool +ix86_expand_movmem (rtx operands[]) +{ + /* Since there are much less registers available in 32-bit mode, don't + inline movmem in 32-bit mode. */ + if (!TARGET_64BIT) + return false; + + rtx dst = operands[0]; + rtx src = operands[1]; + rtx count_exp = operands[2]; + rtx expected_size_exp = operands[5]; + rtx min_size_exp = operands[6]; + rtx probable_max_size_exp = operands[8]; + unsigned HOST_WIDE_INT count = HOST_WIDE_INT_0U; + HOST_WIDE_INT expected_size = HOST_WIDE_INT_M1U; + unsigned HOST_WIDE_INT min_size = HOST_WIDE_INT_0U; + unsigned HOST_WIDE_INT probable_max_size = HOST_WIDE_INT_M1U; + + if (CONST_INT_P (count_exp)) + { + min_size = probable_max_size = count = expected_size + = INTVAL (count_exp); + /* When COUNT is 0, there is nothing to do. */ + if (!count) + return true; + } + else + { + if (min_size_exp) + min_size = INTVAL (min_size_exp); + if (probable_max_size_exp) + probable_max_size = INTVAL (probable_max_size_exp); + if (CONST_INT_P (expected_size_exp)) + expected_size = INTVAL (expected_size_exp); + } + + /* Make sure we don't need to care about overflow later on. */ + if (count > (HOST_WIDE_INT_1U << 30)) + return false; + + addr_space_t dst_as = MEM_ADDR_SPACE (dst); + addr_space_t src_as = MEM_ADDR_SPACE (src); + int dynamic_check; + bool noalign; + enum stringop_alg alg = decide_alg (count, expected_size, min_size, + probable_max_size, false, false, + dst_as, src_as, &dynamic_check, + &noalign, false); + if (alg == libcall) + return false; + + rtx destreg = ix86_copy_addr_to_reg (XEXP (dst, 0)); + rtx srcreg = ix86_copy_addr_to_reg (XEXP (src, 0)); + + unsigned int move_max = MOVE_MAX; + machine_mode mode = smallest_int_mode_for_size + (move_max * BITS_PER_UNIT).require (); + if (probable_max_size && probable_max_size < move_max) + { + /* Get a usable MOVE_MAX. */ + mode = smallest_int_mode_for_size + (probable_max_size * BITS_PER_UNIT).require (); + /* Reduce MOVE_MAX by half so that MOVE_MAX can be used. */ + if (GET_MODE_SIZE (mode) > probable_max_size) + mode = smallest_int_mode_for_size + (GET_MODE_BITSIZE (mode) / 2).require (); + move_max = GET_MODE_SIZE (mode); + } + + /* Try to fully unroll memmove of known size first. */ + if (count + && ix86_expand_unroll_movmem (dst, src, destreg, srcreg, count, + mode)) + return true; + + rtx_code_label *done_label = gen_label_rtx (); + + rtx_code_label *less_vec_label = nullptr; + if (min_size == 0 || min_size < move_max) + less_vec_label = gen_label_rtx (); + + machine_mode count_mode = counter_mode (count_exp); + + /* Jump to LESS_VEC_LABEL if size < MOVE_MAX. */ + if (less_vec_label) + emit_cmp_and_jump_insns (count_exp, GEN_INT (move_max), LTU, + nullptr, count_mode, 1, + less_vec_label); + + rtx_code_label *more_2x_vec_label = nullptr; + if (probable_max_size == 0 || probable_max_size > 2 * move_max) + more_2x_vec_label = gen_label_rtx (); + + /* Jump to MORE_2X_VEC_LABEL if size > 2 * MOVE_MAX. */ + if (more_2x_vec_label) + emit_cmp_and_jump_insns (count_exp, GEN_INT (2 * move_max), GTU, + nullptr, count_mode, 1, + more_2x_vec_label); + + if (min_size == 0 || min_size <= 2 * move_max) + { + /* Size >= MOVE_MAX and size <= 2 * MOVE_MAX. */ + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg, + count_exp, mode, 2); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (less_vec_label) + { + /* Size < MOVE_MAX. */ + emit_label (less_vec_label); + ix86_expand_less_move_movmem (dst, src, destreg, srcreg, + count_exp, min_size, mode, + done_label); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (more_2x_vec_label) + { + /* Size > 2 * MOVE_MAX and destination may overlap with source. */ + emit_label (more_2x_vec_label); + + rtx_code_label *more_8x_vec_label = nullptr; + if (probable_max_size == 0 || probable_max_size > 8 * move_max) + more_8x_vec_label = gen_label_rtx (); + + /* Jump to MORE_8X_VEC_LABEL if size > 8 * MOVE_MAX. */ + if (more_8x_vec_label) + emit_cmp_and_jump_insns (count_exp, GEN_INT (8 * move_max), GTU, + nullptr, count_mode, 1, + more_8x_vec_label); + + rtx_code_label *last_4x_vec_label = nullptr; + if (min_size == 0 || min_size < 4 * move_max) + last_4x_vec_label = gen_label_rtx (); + + /* Jump to LAST_4X_VEC_LABEL if size < 4 * MOVE_MAX. */ + if (last_4x_vec_label) + emit_cmp_and_jump_insns (count_exp, GEN_INT (4 * move_max), LTU, + nullptr, count_mode, 1, + last_4x_vec_label); + + if (probable_max_size == 0 || probable_max_size > 4 * move_max) + { + /* Size > 4 * MOVE_MAX and size <= 8 * MOVE_MAX. */ + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, + srcreg, count_exp, + mode, 8); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (last_4x_vec_label) + { + /* Size > 2 * MOVE_MAX and size <= 4 * MOVE_MAX. */ + emit_label (last_4x_vec_label); + ix86_expand_n_overlapping_move_movmem (dst, src, destreg, + srcreg, count_exp, + mode, 4); + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + + if (more_8x_vec_label) + { + /* Size > 8 * MOVE_MAX. */ + emit_label (more_8x_vec_label); + + rtx loop_count = gen_reg_rtx (count_mode); + emit_move_insn (loop_count, count_exp); + + /* Jump to MORE_8X_VEC_BACKWARD_LABEL if source address is + lower than destination address. */ + rtx_code_label *more_8x_vec_backward_label = gen_label_rtx (); + emit_cmp_and_jump_insns (srcreg, destreg, LTU, nullptr, + GET_MODE (destreg), 1, + more_8x_vec_backward_label); + + /* Skip if source == destination which is less common. */ + emit_cmp_and_jump_insns (srcreg, destreg, EQ, nullptr, + GET_MODE (destreg), 1, done_label, + profile_probability::unlikely ()); + + rtx base_destreg = gen_reg_rtx (GET_MODE (destreg)); + emit_move_insn (base_destreg, destreg); + + /* Load the last 4 * MOVE_MAX. */ + rtx regs[4]; + ix86_expand_load_movmem (src, srcreg, count_exp, mode, + ARRAY_SIZE (regs), regs, true); + + rtx srcmem = change_address (src, mode, srcreg); + rtx destmem = change_address (dst, mode, destreg); + + /* Copy forward with a 4 * MOVE_MAX loop. */ + rtx_code_label *loop_4x_vec_forward_label = gen_label_rtx (); + emit_label (loop_4x_vec_forward_label); + + ix86_expand_n_move_movmem (destmem, srcmem, mode, 4, true); + + rtx tmp; + rtx delta = GEN_INT (4 * MOVE_MAX); + + /* Decrement LOOP_COUNT by 4 * MOVE_MAX. */ + tmp = expand_simple_binop (GET_MODE (loop_count), MINUS, + loop_count, delta, nullptr, 1, + OPTAB_DIRECT); + if (tmp != loop_count) + emit_move_insn (loop_count, tmp); + + /* Increment DESTREG and SRCREG by 4 * MOVE_MAX. */ + tmp = expand_simple_binop (GET_MODE (destreg), PLUS, + destreg, delta, nullptr, 1, + OPTAB_DIRECT); + if (tmp != destreg) + emit_move_insn (destreg, tmp); + tmp = expand_simple_binop (GET_MODE (srcreg), PLUS, srcreg, + delta, nullptr, 1, OPTAB_DIRECT); + if (tmp != srcreg) + emit_move_insn (srcreg, tmp); + + /* Stop if LOOP_EXP <= 4 * MOVE_MAX. */ + emit_cmp_and_jump_insns (loop_count, delta, GTU, nullptr, + GET_MODE (loop_count), 1, + loop_4x_vec_forward_label); + + /* Store the last 4 * MOVE_MAX. */ + ix86_expand_store_movmem (dst, base_destreg, count_exp, mode, + ARRAY_SIZE (regs), regs, true); + + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + + /* Copy backward with a 4 * MOVE_MAX loop. */ + emit_label (more_8x_vec_backward_label); + + base_destreg = gen_reg_rtx (GET_MODE (destreg)); + emit_move_insn (base_destreg, destreg); + + /* Load the first 4 * MOVE_MAX. */ + ix86_expand_load_movmem (src, srcreg, count_exp, mode, + ARRAY_SIZE (regs), regs, false); + + /* Increment DESTREG and SRCREG by COUNT_EXP. */ + tmp = expand_simple_binop (GET_MODE (destreg), PLUS, + destreg, count_exp, nullptr, 1, + OPTAB_DIRECT); + if (tmp != destreg) + emit_move_insn (destreg, tmp); + tmp = expand_simple_binop (GET_MODE (srcreg), PLUS, srcreg, + count_exp, nullptr, 1, OPTAB_DIRECT); + if (tmp != srcreg) + emit_move_insn (srcreg, tmp); + + srcmem = change_address (src, mode, srcreg); + destmem = change_address (dst, mode, destreg); + rtx step = GEN_INT (-GET_MODE_SIZE (mode)); + srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode)); + destmem = offset_address (destmem, step, GET_MODE_SIZE (mode)); + + rtx_code_label *loop_4x_vec_backward_label = gen_label_rtx (); + emit_label (loop_4x_vec_backward_label); + + ix86_expand_n_move_movmem (destmem, srcmem, mode, 4, false); + + /* Decrement LOOP_COUNT by 4 * MOVE_MAX. */ + tmp = expand_simple_binop (GET_MODE (loop_count), MINUS, + loop_count, delta, nullptr, 1, + OPTAB_DIRECT); + if (tmp != loop_count) + emit_move_insn (loop_count, tmp); + + /* Decrement DESTREG and SRCREG by 4 * MOVE_MAX. */ + tmp = expand_simple_binop (GET_MODE (destreg), MINUS, + destreg, delta, nullptr, 1, + OPTAB_DIRECT); + if (tmp != destreg) + emit_move_insn (destreg, tmp); + tmp = expand_simple_binop (GET_MODE (srcreg), MINUS, srcreg, + delta, nullptr, 1, OPTAB_DIRECT); + if (tmp != srcreg) + emit_move_insn (srcreg, tmp); + + /* Stop if LOOP_EXP <= 4 * MOVE_MAX. */ + emit_cmp_and_jump_insns (loop_count, delta, GTU, nullptr, + GET_MODE (loop_count), 1, + loop_4x_vec_backward_label); + + /* Store the first 4 * MOVE_MAX. */ + ix86_expand_store_movmem (dst, base_destreg, count_exp, mode, + ARRAY_SIZE (regs), regs, false); + + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + } + } + + emit_label (done_label); + + return true; +} + /* Expand cmpstrn or memcmp. */ bool diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index bdb8bb9..5ff414a 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -78,6 +78,7 @@ extern void substitute_vpternlog_operands (rtx[]); extern bool ix86_expand_strlen (rtx, rtx, rtx, rtx); extern bool ix86_expand_set_or_cpymem (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, bool); +extern bool ix86_expand_movmem (rtx[]); extern bool ix86_expand_cmpstrn_or_cmpmem (rtx, rtx, rtx, rtx, rtx, bool); extern enum reg_class ix86_insn_base_reg_class (rtx_insn *); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b812d8b..7ec028c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -25708,6 +25708,23 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) +(define_expand "movmem<mode>" + [(use (match_operand:BLK 0 "memory_operand")) + (use (match_operand:BLK 1 "memory_operand")) + (use (match_operand:SWI48 2 "nonmemory_operand")) + (use (match_operand:SWI48 3 "const_int_operand")) + (use (match_operand:SI 4 "const_int_operand")) + (use (match_operand:SI 5 "const_int_operand")) + (use (match_operand:SI 6 "")) + (use (match_operand:SI 7 "")) + (use (match_operand:SI 8 ""))] + "" +{ + if (ix86_expand_movmem (operands)) + DONE; + FAIL; +}) + (define_expand "cpymem<mode>" [(use (match_operand:BLK 0 "memory_operand")) (use (match_operand:BLK 1 "memory_operand")) diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md index 7a91473..71dd25d0 100644 --- a/gcc/config/loongarch/lasx.md +++ b/gcc/config/loongarch/lasx.md @@ -130,6 +130,7 @@ ;; Only used for splitting insert_d and copy_{u,s}.d. (define_mode_iterator LASX_WD [V4DI V4DF V8SI V8SF]) +(define_mode_iterator LASX_PART [V4DI V4DF V8SF]) ;; Only used for copy256_{u,s}.w. (define_mode_iterator LASX_W [V8SI V8SF]) @@ -514,7 +515,7 @@ (set_attr "mode" "<MODE>")]) ;; xvpermi.q -(define_insn "lasx_xvpermi_q_<LASX:mode>" +(define_insn_and_split "lasx_xvpermi_q_<LASX:mode>" [(set (match_operand:LASX 0 "register_operand" "=f") (unspec:LASX [(match_operand:LASX 1 "register_operand" "0") @@ -525,6 +526,37 @@ { return "xvpermi.q\t%u0,%u2,%3"; } + "&& ((INTVAL (operands[3]) & 0xee) == 0x0 + || (INTVAL (operands[3]) & 0xee) == 0x22)" + [(const_int 0)] +{ + HOST_WIDE_INT selector = INTVAL (operands[3]); + /* Reduce the dependency caused by using output operands[0] as input. */ + switch (INTVAL (operands[3])) + { + case 0x22: + case 0x23: + case 0x33: + selector -= 0x22; + operands[2] = operands[1]; + /* FALLTHRU. */ + case 0x0: + case 0x1: + case 0x11: + emit_insn (gen_lasx_xvpermi_d_<mode> (operands[0], operands[2], + GEN_INT (selector * 0xa + 0x44))); + break; + case 0x10: + emit_move_insn (operands[0], operands[2]); + break; + case 0x32: + emit_move_insn (operands[0], operands[1]); + break; + default: + gcc_unreachable (); + } + DONE; +} [(set_attr "type" "simd_splat") (set_attr "mode" "<MODE>")]) @@ -672,6 +704,41 @@ [(set_attr "move_type" "fmove") (set_attr "mode" "<MODE>")]) +;; vr0 -> low xr0 +;; +(define_insn "vec_cast<mode>" + [(set (match_operand:LASX_PART 0 "register_operand" "=f") + (subreg:LASX_PART + (match_operand:<VHMODE256_ALL> 1 "register_operand" "0") 0))] + "ISA_HAS_LASX" + "" + [(set_attr "type" "simd_splat") + (set_attr "mode" "<MODE>")]) + +(define_insn "vec_insert_lo_<mode>" + [(set (match_operand:LASX_PART 0 "register_operand" "=f") + (vec_concat:LASX_PART + (match_operand:<VHMODE256_ALL> 2 "register_operand" "f") + (vec_select:<VHMODE256_ALL> + (match_operand:LASX_PART 1 "register_operand" "0") + (match_operand:LASX_PART 3 "vect_par_cnst_high_half"))))] + "ISA_HAS_LASX" + "xvpermi.q\t%u0,%u2,0x30" + [(set_attr "type" "simd_splat") + (set_attr "mode" "<MODE>")]) + +(define_insn "vec_insert_hi_<mode>" + [(set (match_operand:LASX_PART 0 "register_operand" "=f") + (vec_concat:LASX_PART + (vec_select:<VHMODE256_ALL> + (match_operand:LASX_PART 1 "register_operand" "0") + (match_operand:LASX_PART 3 "vect_par_cnst_low_half")) + (match_operand:<VHMODE256_ALL> 2 "register_operand" "f")))] + "ISA_HAS_LASX" + "xvpermi.q\t%u0,%u2,0x02" + [(set_attr "type" "simd_splat") + (set_attr "mode" "<MODE>")]) + (define_expand "vec_perm<mode>" [(match_operand:LASX 0 "register_operand") (match_operand:LASX 1 "register_operand") diff --git a/gcc/config/loongarch/lasxintrin.h b/gcc/config/loongarch/lasxintrin.h index 6bcffc2..6c34ede 100644 --- a/gcc/config/loongarch/lasxintrin.h +++ b/gcc/config/loongarch/lasxintrin.h @@ -23,6 +23,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ +#include <lsxintrin.h> + #ifndef _GCC_LOONGSON_ASXINTRIN_H #define _GCC_LOONGSON_ASXINTRIN_H 1 @@ -5368,5 +5370,159 @@ __m256i __lasx_xvfcmp_sun_s (__m256 _1, __m256 _2) #define __lasx_xvrepli_w(/*si10*/ _1) \ ((__m256i)__builtin_lasx_xvrepli_w ((_1))) +#if defined (__loongarch_asx_sx_conv) +/* Add builtin interfaces for 128 and 256 vector conversions. + For the assembly instruction format of some functions of the following vector + conversion, it is not described exactly in accordance with the format of the + generated assembly instruction. + In the front end of the Rust language, different built-in functions are called + by analyzing the format of assembly instructions. The data types of instructions + are all defined based on the interfaces of the defined functions, in the + following order: output, input... . */ +/* Assembly instruction format: xd, vj. */ +/* Data types in instruction templates: V8SF, V4SF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256 __lasx_cast_128_s (__m128 _1) +{ + return (__m256)__builtin_lasx_cast_128_s ((v4f32)_1); +} + +/* Assembly instruction format: xd, vj. */ +/* Data types in instruction templates: V4DF, V2DF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256d __lasx_cast_128_d (__m128d _1) +{ + return (__m256d)__builtin_lasx_cast_128_d ((v2f64)_1); +} + +/* Assembly instruction format: xd, vj. */ +/* Data types in instruction templates: V4DI, V2DI. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256i __lasx_cast_128 (__m128i _1) +{ + return (__m256i)__builtin_lasx_cast_128 ((v2i64)_1); +} + +/* Assembly instruction format: xd, vj, vk. */ +/* Data types in instruction templates: V8SF, V4SF, V4SF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256 __lasx_concat_128_s (__m128 _1, __m128 _2) +{ + return (__m256)__builtin_lasx_concat_128_s ((v4f32)_1, (v4f32)_2); +} + +/* Assembly instruction format: xd, vj, vk. */ +/* Data types in instruction templates: V4DF, V2DF, V2DF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256d __lasx_concat_128_d (__m128d _1, __m128d _2) +{ + return (__m256d)__builtin_lasx_concat_128_d ((v2f64)_1, (v2f64)_2); +} + +/* Assembly instruction format: xd, vj, vk. */ +/* Data types in instruction templates: V4DI, V2DI, V2DI. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256i __lasx_concat_128 (__m128i _1, __m128i _2) +{ + return (__m256i)__builtin_lasx_concat_128 ((v2i64)_1, (v2i64)_2); +} + +/* Assembly instruction format: vd, xj. */ +/* Data types in instruction templates: V4SF, V8SF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m128 __lasx_extract_128_lo_s (__m256 _1) +{ + return (__m128)__builtin_lasx_extract_128_lo_s ((v8f32)_1); +} + +/* Assembly instruction format: vd, xj. */ +/* Data types in instruction templates: V4SF, V8SF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m128 __lasx_extract_128_hi_s (__m256 _1) +{ + return (__m128)__builtin_lasx_extract_128_hi_s ((v8f32)_1); +} + +/* Assembly instruction format: vd, xj. */ +/* Data types in instruction templates: V2DF, V4DF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m128d __lasx_extract_128_lo_d (__m256d _1) +{ + return (__m128d)__builtin_lasx_extract_128_lo_d ((v4f64)_1); +} + +/* Assembly instruction format: vd, xj. */ +/* Data types in instruction templates: V2DF, V4DF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m128d __lasx_extract_128_hi_d (__m256d _1) +{ + return (__m128d)__builtin_lasx_extract_128_hi_d ((v4f64)_1); +} + +/* Assembly instruction format: vd, xj. */ +/* Data types in instruction templates: V2DI, V4DI. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m128i __lasx_extract_128_lo (__m256i _1) +{ + return (__m128i)__builtin_lasx_extract_128_lo ((v4i64)_1); +} + +/* Assembly instruction format: vd, xj. */ +/* Data types in instruction templates: V2DI, V4DI. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m128i __lasx_extract_128_hi (__m256i _1) +{ + return (__m128i)__builtin_lasx_extract_128_hi ((v4i64)_1); +} + +/* Assembly instruction format: xd, xj, vk. */ +/* Data types in instruction templates: V8SF, V8SF, V4SF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256 __lasx_insert_128_lo_s (__m256 _1, __m128 _2) +{ + return (__m256)__builtin_lasx_insert_128_lo_s ((v8f32)_1, (v4f32)_2); +} + +/* Assembly instruction format: xd, xj, vk. */ +/* Data types in instruction templates: V8SF, V8SF, V4SF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256 __lasx_insert_128_hi_s (__m256 _1, __m128 _2) +{ + return (__m256)__builtin_lasx_insert_128_hi_s ((v8f32)_1, (v4f32)_2); +} + +/* Assembly instruction format: xd, xj, vk. */ +/* Data types in instruction templates: V4DF, V4DF, V2DF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256d __lasx_insert_128_lo_d (__m256d _1, __m128d _2) +{ + return (__m256d)__builtin_lasx_insert_128_lo_d ((v4f64)_1, (v2f64)_2); +} + +/* Assembly instruction format: xd, xj, vk. */ +/* Data types in instruction templates: V4DF, V4DF, V2DF. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256d __lasx_insert_128_hi_d (__m256d _1, __m128d _2) +{ + return (__m256d)__builtin_lasx_insert_128_hi_d ((v4f64)_1, (v2f64)_2); +} + +/* Assembly instruction format: xd, xj, vk. */ +/* Data types in instruction templates: V4DI, V4DI, V2DI. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256i __lasx_insert_128_lo (__m256i _1, __m128i _2) +{ + return (__m256i)__builtin_lasx_insert_128_lo ((v4i64)_1, (v2i64)_2); +} + +/* Assembly instruction format: xd, xj, vk. */ +/* Data types in instruction templates: V4DI, V4DI, V2DI. */ +extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +__m256i __lasx_insert_128_hi (__m256i _1, __m128i _2) +{ + return (__m256i)__builtin_lasx_insert_128_hi ((v4i64)_1, (v2i64)_2); +} + +#endif /* defined(__loongarch_asx_sx_conv). */ #endif /* defined(__loongarch_asx). */ #endif /* _GCC_LOONGSON_ASXINTRIN_H. */ diff --git a/gcc/config/loongarch/loongarch-builtins.cc b/gcc/config/loongarch/loongarch-builtins.cc index 9493ded..312d876 100644 --- a/gcc/config/loongarch/loongarch-builtins.cc +++ b/gcc/config/loongarch/loongarch-builtins.cc @@ -865,6 +865,27 @@ AVAIL_ALL (lasx_frecipe, ISA_HAS_LASX && ISA_HAS_FRECIPE) #define CODE_FOR_lasx_xvmaddwod_q_du CODE_FOR_lasx_maddwod_q_du_punned #define CODE_FOR_lasx_xvmaddwod_q_du_d CODE_FOR_lasx_maddwod_q_du_d_punned + +/* Add mutual conversion between 128 and 256 vectors. */ +#define CODE_FOR_lasx_extract_128_lo_s CODE_FOR_vec_extract_lo_v8sf +#define CODE_FOR_lasx_extract_128_hi_s CODE_FOR_vec_extract_hi_v8sf +#define CODE_FOR_lasx_extract_128_lo_d CODE_FOR_vec_extract_lo_v4df +#define CODE_FOR_lasx_extract_128_hi_d CODE_FOR_vec_extract_hi_v4df +#define CODE_FOR_lasx_extract_128_lo CODE_FOR_vec_extract_lo_v4di +#define CODE_FOR_lasx_extract_128_hi CODE_FOR_vec_extract_hi_v4di +#define CODE_FOR_lasx_insert_128_lo_s CODE_FOR_vec_insert_lo_v8sf +#define CODE_FOR_lasx_insert_128_hi_s CODE_FOR_vec_insert_hi_v8sf +#define CODE_FOR_lasx_insert_128_lo_d CODE_FOR_vec_insert_lo_v4df +#define CODE_FOR_lasx_insert_128_hi_d CODE_FOR_vec_insert_hi_v4df +#define CODE_FOR_lasx_insert_128_lo CODE_FOR_vec_insert_lo_v4di +#define CODE_FOR_lasx_insert_128_hi CODE_FOR_vec_insert_hi_v4di +#define CODE_FOR_lasx_concat_128_s CODE_FOR_vec_concatv8sf +#define CODE_FOR_lasx_concat_128_d CODE_FOR_vec_concatv4df +#define CODE_FOR_lasx_concat_128 CODE_FOR_vec_concatv4di +#define CODE_FOR_lasx_cast_128_s CODE_FOR_vec_castv8sf +#define CODE_FOR_lasx_cast_128_d CODE_FOR_vec_castv4df +#define CODE_FOR_lasx_cast_128 CODE_FOR_vec_castv4di + static const struct loongarch_builtin_description loongarch_builtins[] = { #define LARCH_MOVFCSR2GR 0 DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float), @@ -2407,7 +2428,25 @@ static const struct loongarch_builtin_description loongarch_builtins[] = { LASX_BUILTIN (xvssrarni_bu_h, LARCH_UV32QI_FTYPE_UV32QI_V32QI_USI), LASX_BUILTIN (xvssrarni_hu_w, LARCH_UV16HI_FTYPE_UV16HI_V16HI_USI), LASX_BUILTIN (xvssrarni_wu_d, LARCH_UV8SI_FTYPE_UV8SI_V8SI_USI), - LASX_BUILTIN (xvssrarni_du_q, LARCH_UV4DI_FTYPE_UV4DI_V4DI_USI) + LASX_BUILTIN (xvssrarni_du_q, LARCH_UV4DI_FTYPE_UV4DI_V4DI_USI), + LASX_BUILTIN (extract_128_lo_s, LARCH_V4SF_FTYPE_V8SF), + LASX_BUILTIN (extract_128_hi_s, LARCH_V4SF_FTYPE_V8SF), + LASX_BUILTIN (extract_128_lo_d, LARCH_V2DF_FTYPE_V4DF), + LASX_BUILTIN (extract_128_hi_d, LARCH_V2DF_FTYPE_V4DF), + LASX_BUILTIN (extract_128_lo, LARCH_V2DI_FTYPE_V4DI), + LASX_BUILTIN (extract_128_hi, LARCH_V2DI_FTYPE_V4DI), + LASX_BUILTIN (insert_128_lo_s, LARCH_V8SF_FTYPE_V8SF_V4SF), + LASX_BUILTIN (insert_128_hi_s, LARCH_V8SF_FTYPE_V8SF_V4SF), + LASX_BUILTIN (insert_128_lo_d, LARCH_V4DF_FTYPE_V4DF_V2DF), + LASX_BUILTIN (insert_128_hi_d, LARCH_V4DF_FTYPE_V4DF_V2DF), + LASX_BUILTIN (insert_128_lo, LARCH_V4DI_FTYPE_V4DI_V2DI), + LASX_BUILTIN (insert_128_hi, LARCH_V4DI_FTYPE_V4DI_V2DI), + LASX_BUILTIN (concat_128_s, LARCH_V8SF_FTYPE_V4SF_V4SF), + LASX_BUILTIN (concat_128_d, LARCH_V4DF_FTYPE_V2DF_V2DF), + LASX_BUILTIN (concat_128, LARCH_V4DI_FTYPE_V2DI_V2DI), + LASX_BUILTIN (cast_128_s, LARCH_V8SF_FTYPE_V4SF), + LASX_BUILTIN (cast_128_d, LARCH_V4DF_FTYPE_V2DF), + LASX_BUILTIN (cast_128, LARCH_V4DI_FTYPE_V2DI) }; /* Index I is the function declaration for loongarch_builtins[I], or null if @@ -3001,6 +3040,10 @@ loongarch_expand_builtin_direct (enum insn_code icode, rtx target, tree exp, { struct expand_operand ops[MAX_RECOG_OPERANDS]; int opno, argno; + /* For vector extraction/insertion operations, sel_high_p being true + indicates that the high of the data is selected/retained from the + vector register. */ + bool sel_high_p = true; /* Map any target to operand 0. */ opno = 0; @@ -3019,6 +3062,51 @@ loongarch_expand_builtin_direct (enum insn_code icode, rtx target, tree exp, create_input_operand (&ops[1], CONST1_RTX (ops[0].mode), ops[0].mode); return loongarch_expand_builtin_insn (icode, 3, ops, has_target_p); + case CODE_FOR_vec_extract_lo_v8sf: + case CODE_FOR_vec_extract_lo_v4df: + case CODE_FOR_vec_extract_lo_v4di: + sel_high_p = false; + /* Fall through. */ + case CODE_FOR_vec_extract_hi_v8sf: + case CODE_FOR_vec_extract_hi_v4df: + case CODE_FOR_vec_extract_hi_v4di: + { + /* The selection method for constructing the high/low half. */ + loongarch_prepare_builtin_arg (&ops[1], exp, 0); + int nelts = GET_MODE_NUNITS (GET_MODE (ops[1].value)); + int half_nelts = nelts / 2; + int base = sel_high_p ? half_nelts : 0; + + rtx pat_rtx + = loongarch_gen_stepped_int_parallel (half_nelts, base, 1); + create_input_operand (&ops[2], pat_rtx, ops[1].mode); + + return loongarch_expand_builtin_insn (icode, 3, ops, has_target_p); + } + + case CODE_FOR_vec_insert_hi_v8sf: + case CODE_FOR_vec_insert_hi_v4df: + case CODE_FOR_vec_insert_hi_v4di: + sel_high_p = false; + /* Fall through. */ + case CODE_FOR_vec_insert_lo_v8sf: + case CODE_FOR_vec_insert_lo_v4df: + case CODE_FOR_vec_insert_lo_v4di: + { + /* The selection method for constructing the high/low half. */ + loongarch_prepare_builtin_arg (&ops[1], exp, 0); + loongarch_prepare_builtin_arg (&ops[2], exp, 1); + int nelts = GET_MODE_NUNITS (GET_MODE (ops[1].value)); + int half_nelts = nelts / 2; + int base = sel_high_p ? half_nelts : 0; + + rtx pat_rtx + = loongarch_gen_stepped_int_parallel (half_nelts, base, 1); + create_input_operand (&ops[3], pat_rtx, ops[1].mode); + + return loongarch_expand_builtin_insn (icode, 4, ops, has_target_p); + } + default: break; } diff --git a/gcc/config/loongarch/loongarch-c.cc b/gcc/config/loongarch/loongarch-c.cc index effdcf0..fc031a6 100644 --- a/gcc/config/loongarch/loongarch-c.cc +++ b/gcc/config/loongarch/loongarch-c.cc @@ -132,6 +132,7 @@ loongarch_update_cpp_builtins (cpp_reader *pfile) loongarch_def_or_undef (ISA_HAS_LSX, "__loongarch_simd", pfile); loongarch_def_or_undef (ISA_HAS_LSX, "__loongarch_sx", pfile); loongarch_def_or_undef (ISA_HAS_LASX, "__loongarch_asx", pfile); + loongarch_def_or_undef (ISA_HAS_LASX, "__loongarch_asx_sx_conv", pfile); builtin_undef ("__loongarch_simd_width"); if (ISA_HAS_LSX) diff --git a/gcc/config/loongarch/loongarch-ftypes.def b/gcc/config/loongarch/loongarch-ftypes.def index 337f2c2..68b1b44 100644 --- a/gcc/config/loongarch/loongarch-ftypes.def +++ b/gcc/config/loongarch/loongarch-ftypes.def @@ -42,6 +42,12 @@ DEF_LARCH_FTYPE (1, (USI, USI)) DEF_LARCH_FTYPE (1, (UDI, USI)) DEF_LARCH_FTYPE (1, (USI, UQI)) DEF_LARCH_FTYPE (1, (VOID, USI)) +DEF_LARCH_FTYPE (1, (V4SF, V8SF)) +DEF_LARCH_FTYPE (1, (V2DF, V4DF)) +DEF_LARCH_FTYPE (1, (V2DI, V4DI)) +DEF_LARCH_FTYPE (1, (V8SF, V4SF)) +DEF_LARCH_FTYPE (1, (V4DF, V2DF)) +DEF_LARCH_FTYPE (1, (V4DI, V2DI)) DEF_LARCH_FTYPE (2, (VOID, UQI, USI)) DEF_LARCH_FTYPE (2, (VOID, UHI, USI)) @@ -58,6 +64,12 @@ DEF_LARCH_FTYPE (2, (SI, SI, SI)) DEF_LARCH_FTYPE (2, (SI, DI, SI)) DEF_LARCH_FTYPE (2, (USI, USI, USI)) DEF_LARCH_FTYPE (2, (UDI, UDI, USI)) +DEF_LARCH_FTYPE (2, (V8SF, V4SF, V4SF)) +DEF_LARCH_FTYPE (2, (V4DF, V2DF, V2DF)) +DEF_LARCH_FTYPE (2, (V4DI, V2DI, V2DI)) +DEF_LARCH_FTYPE (2, (V8SF, V8SF, V4SF)) +DEF_LARCH_FTYPE (2, (V4DF, V4DF, V2DF)) +DEF_LARCH_FTYPE (2, (V4DI, V4DI, V2DI)) DEF_LARCH_FTYPE (3, (VOID, USI, USI, SI)) DEF_LARCH_FTYPE (3, (VOID, USI, UDI, SI)) diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h index bec4368..e00dd89 100644 --- a/gcc/config/loongarch/loongarch-protos.h +++ b/gcc/config/loongarch/loongarch-protos.h @@ -159,6 +159,7 @@ extern bool loongarch_use_ins_ext_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT); extern bool loongarch_check_zero_div_p (void); extern bool loongarch_pre_reload_split (void); extern int loongarch_use_bstrins_for_ior_with_mask (machine_mode, rtx *); +extern bool loongarch_use_bstrins_bstrpick_for_and (rtx, machine_mode); extern rtx loongarch_rewrite_mem_for_simple_ldst (rtx); union loongarch_gen_fn_ptrs diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index f7ce3aa..d11fe49 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -3439,13 +3439,8 @@ loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value) x = GEN_INT (codes[0].value); for (i = 1; i < num_ops; i++) { - if (!can_create_pseudo_p ()) - { - emit_insn (gen_rtx_SET (temp, x)); - x = temp; - } - else - x = force_reg (mode, x); + emit_insn (gen_rtx_SET (temp, x)); + x = temp; set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (codes[i-1].curr_value)); @@ -3803,6 +3798,34 @@ loongarch_use_bstrins_for_ior_with_mask_1 (machine_mode mode, return 0; } +/* Check if it is possible to optimize AND operation with an immediate: + a. immediate is loaded by more than 1 instruction + b. can use bstrpick.d + bstrins.d. */ + +bool +loongarch_use_bstrins_bstrpick_for_and (rtx op, machine_mode mode) +{ + if (!TARGET_64BIT) + return false; + + /* Avoid aggressive optimization of combine before reload. */ + if (!reload_completed) + return false; + + /* It's meaningless if the OP is not splittable + and skip the cases already supported in AND operation. */ + if (!splittable_const_int_operand (op, mode) || and_operand (op, mode)) + return false; + + int leading_zero_bit = __builtin_clzll (UINTVAL (op)); + unsigned HOST_WIDE_INT mask = (~0ULL) << (64 - leading_zero_bit); + + if (ins_zero_bitmask_operand (GEN_INT (UINTVAL (op) | mask), mode)) + return true; + + return false; +} + /* Return the cost of moving between two registers of mode MODE. */ static int @@ -3922,14 +3945,24 @@ loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code, return false; case AND: - /* Check for a *clear_upper32 pattern and treat it like a zero - extension. See the pattern's comment for details. */ - if (TARGET_64BIT && mode == DImode && CONST_INT_P (XEXP (x, 1)) - && UINTVAL (XEXP (x, 1)) == 0xffffffff) + if (TARGET_64BIT && mode == DImode && CONST_INT_P (XEXP (x, 1))) { - *total = (loongarch_zero_extend_cost (XEXP (x, 0)) - + set_src_cost (XEXP (x, 0), mode, speed)); - return true; + /* Check for a *clear_upper32 pattern and treat it like a zero + extension. See the pattern's comment for details. */ + if (UINTVAL (XEXP (x, 1)) == 0xffffffff) + { + *total = (loongarch_zero_extend_cost (XEXP (x, 0)) + + set_src_cost (XEXP (x, 0), mode, speed)); + return true; + } + /* Check if it can be done by bstrpick.d and bstrins.d. */ + else if (loongarch_use_bstrins_bstrpick_for_and (XEXP (x, 1), mode)) + { + /* The pattern will be split into 2 insns. */ + *total = (COSTS_N_INSNS (2) + + set_src_cost (XEXP (x, 0), mode, speed)); + return true; + } } /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in a single instruction. */ @@ -3983,9 +4016,34 @@ loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code, speed); return true; + case LSHIFTRT: + /* Correct the cost of mulh.{w[u]/d[u]}. */ + if (outer_code == TRUNCATE && CONST_INT_P (XEXP (x, 1)) + && INTVAL (XEXP (x, 1)) == (GET_MODE_BITSIZE (mode) / 2) + && GET_CODE (XEXP (x, 0)) == MULT + && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND + && GET_CODE (XEXP (XEXP (x, 0), 1)) == ZERO_EXTEND) + || (GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND + && GET_CODE (XEXP (XEXP (x, 0), 1)) == SIGN_EXTEND)) + && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == REG + && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == REG) + { + if (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SImode + && GET_MODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == SImode) + { + *total = loongarch_cost->int_mult_si; + return true; + } + if (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == DImode + && GET_MODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == DImode) + { + *total = loongarch_cost->int_mult_di; + return true; + } + } + /* Fall through. */ case ASHIFT: case ASHIFTRT: - case LSHIFTRT: case ROTATE: case ROTATERT: if (CONSTANT_P (XEXP (x, 1))) @@ -4234,7 +4292,8 @@ loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code, machine_mode loongarch_split_reduction (machine_mode mode) { - if (LSX_SUPPORTED_MODE_P (mode)) + if (!VECTOR_MODE_P (mode) + || LSX_SUPPORTED_MODE_P (mode)) return mode; return mode_for_vector (as_a <scalar_mode> (GET_MODE_INNER (mode)), @@ -7087,6 +7146,10 @@ static bool loongarch_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t rclass) { + if ((INTEGRAL_MODE_P (from) && FLOAT_MODE_P (to)) + || (INTEGRAL_MODE_P (to) && FLOAT_MODE_P (from))) + return true; + /* Allow conversions between different LSX/LASX vector modes. */ if (LASX_SUPPORTED_MODE_P (from) && LASX_SUPPORTED_MODE_P (to)) return true; @@ -7133,7 +7196,11 @@ loongarch_modes_tieable_p (machine_mode mode1, machine_mode mode2) prefer to put one of them in FPRs. */ return (mode1 == mode2 || (!loongarch_mode_ok_for_mov_fmt_p (mode1) - && !loongarch_mode_ok_for_mov_fmt_p (mode2))); + && !loongarch_mode_ok_for_mov_fmt_p (mode2)) + || (GET_MODE_CLASS(mode1) == MODE_FLOAT + && GET_MODE_CLASS(mode2) == MODE_INT) + || (GET_MODE_CLASS(mode2) == MODE_FLOAT + && GET_MODE_CLASS(mode1) == MODE_INT)); } /* Implement TARGET_PREFERRED_RELOAD_CLASS. */ diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index 625f30c..2f4817d 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -1636,6 +1636,21 @@ operands[3] = tmp; }) +(define_insn "and_load_zero_extend<mode>" + [(set (match_operand:X 0 "register_operand" "=r,r,r,r,r,r") + (and:X (match_operand:X 1 "memory_operand" "%m,m,m,k,k,k") + (match_operand:X 2 "mask_operand" "Yb,Yh,Yw,Yb,Yh,Yw")))] + "" + "@ + ld.bu\t%0,%1 + ld.hu\t%0,%1 + ld.wu\t%0,%1 + ldx.bu\t%0,%1 + ldx.hu\t%0,%1 + ldx.wu\t%0,%1" + [(set_attr "move_type" "load,load,load,load,load,load") + (set_attr "mode" "<MODE>")]) + ;; We always avoid the shift operation in bstrins_<mode>_for_ior_mask ;; if possible, but the result may be sub-optimal when one of the masks ;; is (1 << N) - 1 and one of the src register is the dest register. @@ -1670,6 +1685,24 @@ DONE; }) +(define_insn_and_split "bstrins_bstrpick_for_and_imm<mode>" + [(set (match_operand:X 0 "register_operand" "=r") + (and:X (match_operand:X 1 "register_operand" "r") + (match_operand:X 2 "const_int_operand" "i")))] + "loongarch_use_bstrins_bstrpick_for_and (operands[2], <MODE>mode)" + "#" + "&& true" + [(const_int 0)] +{ + unsigned HOST_WIDE_INT op2 = INTVAL (operands[2]); + int leading_zero_bit = __builtin_clzll (op2); + unsigned HOST_WIDE_INT mask = (~0ULL) << (64 - leading_zero_bit); + emit_insn (gen_extzv<mode> (operands[0], operands[1], + GEN_INT (64 - leading_zero_bit), const0_rtx)); + emit_insn (gen_and<mode>3 (operands[0], operands[0], GEN_INT (op2 | mask))); +} + [(set_attr "length" "8")]) + (define_insn "*iorhi3" [(set (match_operand:HI 0 "register_operand" "=r,r") (ior:HI (match_operand:HI 1 "register_operand" "%r,r") @@ -2306,8 +2339,8 @@ }) (define_insn_and_split "*movsi_internal" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,w,*f,f,*r,*m") - (match_operand:SI 1 "move_operand" "r,Yd,w,rJ,*r*J,m,*f,*f"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,w,f,f,r,*m") + (match_operand:SI 1 "move_operand" "r,Yd,w,rJ,rJ,m,f,*f"))] "(register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode))" { return loongarch_output_move (operands); } diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md index 34cf74d..8460618 100644 --- a/gcc/config/loongarch/predicates.md +++ b/gcc/config/loongarch/predicates.md @@ -413,6 +413,11 @@ (match_operand 0 "low_bitmask_operand") (match_operand 0 "ins_zero_bitmask_operand"))) +(define_predicate "mask_operand" + (ior (match_operand 0 "qi_mask_operand") + (match_operand 0 "hi_mask_operand") + (match_operand 0 "si_mask_operand"))) + (define_predicate "const_call_insn_operand" (match_code "const,symbol_ref,label_ref") { diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index e978f92..e186c6a 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -5886,11 +5886,47 @@ static int riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field *fields, int n, HOST_WIDE_INT offset, bool ignore_zero_width_bit_field_p, + bool ignore_empty_union_and_zero_len_array_p, bool vls_p = false, unsigned abi_vlen = 0) { int max_aggregate_field = vls_p ? 8 : 2; switch (TREE_CODE (type)) { + case UNION_TYPE: + { + if (!ignore_empty_union_and_zero_len_array_p) + return -1; + /* Empty union should ignore. */ + if (TYPE_SIZE (type) == NULL || integer_zerop (TYPE_SIZE (type))) + return n; + /* Or all union member are empty union or empty struct. */ + for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f)) + { + if (TREE_CODE (f) != FIELD_DECL) + continue; + int m; + HOST_WIDE_INT pos = offset + int_byte_position (f); + switch (TREE_CODE (TREE_TYPE (f))) + { + case ARRAY_TYPE: + case UNION_TYPE: + case RECORD_TYPE: + m = riscv_flatten_aggregate_field ( + TREE_TYPE (f), fields, n, pos, + ignore_zero_width_bit_field_p, + true); + /* Any non-empty struct/union/array will stop the flatten. */ + if (m != n) + return -1; + break; + default: + /* Any member are not struct, union or array will stop the + flatten. */ + return -1; + } + } + return n; + } case RECORD_TYPE: /* Can't handle incomplete types nor sizes that are not fixed. */ if (!COMPLETE_TYPE_P (type) @@ -5916,7 +5952,9 @@ riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field *fields, { HOST_WIDE_INT pos = offset + int_byte_position (f); n = riscv_flatten_aggregate_field ( - TREE_TYPE (f), fields, n, pos, ignore_zero_width_bit_field_p, + TREE_TYPE (f), fields, n, pos, + ignore_zero_width_bit_field_p, + ignore_empty_union_and_zero_len_array_p, vls_p, abi_vlen); } if (n < 0) @@ -5930,14 +5968,20 @@ riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field *fields, riscv_aggregate_field subfields[8]; tree index = TYPE_DOMAIN (type); tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); + + /* Array with zero size member should be ignored. */ + if (ignore_empty_union_and_zero_len_array_p && integer_zerop (elt_size)) + return n; + int n_subfields - = riscv_flatten_aggregate_field (TREE_TYPE (type), subfields, 0, - offset, - ignore_zero_width_bit_field_p, vls_p, - abi_vlen); + = riscv_flatten_aggregate_field ( + TREE_TYPE (type), subfields, 0, + offset, + ignore_zero_width_bit_field_p, + ignore_empty_union_and_zero_len_array_p, + vls_p, abi_vlen); /* Can't handle incomplete types nor sizes that are not fixed. */ - if (n_subfields <= 0 - || !COMPLETE_TYPE_P (type) + if (!COMPLETE_TYPE_P (type) || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST || !index || !TYPE_MAX_VALUE (index) @@ -5947,6 +5991,15 @@ riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field *fields, || !tree_fits_uhwi_p (elt_size)) return -1; + /* Zero-length array with empty union/struct should be ignored. */ + if (ignore_empty_union_and_zero_len_array_p && n_subfields == 0 + && integer_zerop (TYPE_MIN_VALUE (index)) + && integer_all_onesp (TYPE_MAX_VALUE (index))) + return n; + + if (n_subfields <= 0) + return -1; + n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) - tree_to_uhwi (TYPE_MIN_VALUE (index)); gcc_assert (n_elts >= 0); @@ -6026,14 +6079,25 @@ static int riscv_flatten_aggregate_argument (const_tree type, riscv_aggregate_field *fields, bool ignore_zero_width_bit_field_p, + bool ignore_empty_union_and_zero_len_array_p, bool vls_p = false, unsigned abi_vlen = 0) { if (!type || TREE_CODE (type) != RECORD_TYPE) return -1; return riscv_flatten_aggregate_field (type, fields, 0, 0, - ignore_zero_width_bit_field_p, vls_p, - abi_vlen); + ignore_zero_width_bit_field_p, + ignore_empty_union_and_zero_len_array_p, + vls_p, abi_vlen); +} + +static bool +riscv_any_non_float_type_field (riscv_aggregate_field *fields, int n) +{ + for (int i = 0; i < n; i++) + if (!SCALAR_FLOAT_TYPE_P (fields[i].type)) + return true; + return false; } /* See whether TYPE is a record whose fields should be returned in one or @@ -6044,24 +6108,18 @@ riscv_pass_aggregate_in_fpr_pair_p (const_tree type, riscv_aggregate_field fields[2]) { static int warned = 0; + if (!type) + return 0; /* This is the old ABI, which differs for C++ and C. */ - int n_old = riscv_flatten_aggregate_argument (type, fields, false); - for (int i = 0; i < n_old; i++) - if (!SCALAR_FLOAT_TYPE_P (fields[i].type)) - { - n_old = -1; - break; - } + int n_old = riscv_flatten_aggregate_argument (type, fields, false, false); + if (riscv_any_non_float_type_field (fields, n_old)) + n_old = -1; /* This is the new ABI, which is the same for C++ and C. */ - int n_new = riscv_flatten_aggregate_argument (type, fields, true); - for (int i = 0; i < n_new; i++) - if (!SCALAR_FLOAT_TYPE_P (fields[i].type)) - { - n_new = -1; - break; - } + int n_new = riscv_flatten_aggregate_argument (type, fields, true, false); + if (riscv_any_non_float_type_field (fields, n_new)) + n_new = -1; if ((n_old != n_new) && (warned == 0)) { @@ -6070,7 +6128,58 @@ riscv_pass_aggregate_in_fpr_pair_p (const_tree type, warned = 1; } - return n_new > 0 ? n_new : 0; + /* ABI with fixing flatten empty union. */ + int n_new2 = riscv_flatten_aggregate_argument (type, fields, true, true); + if (riscv_any_non_float_type_field (fields, n_new2)) + n_new2 = -1; + + bool num_fpr = riscv_pass_mode_in_fpr_p (TYPE_MODE (type)); + + /* There is a special case for struct with zero length array with struct and a + floating point member. + e.g: + struct S0ae_1f { + struct { + } e1[0]; + float f; + }; + + This case we will got 1, but legacy ABI will got -1, however legacy ABI + will got 1 in later logic, so we should consider this case as compatible. + */ + bool compatible_p = n_new2 == 1 && n_new == -1 && num_fpr == 1; + + if ((n_new2 != n_new) + && !compatible_p && (warned == 0)) + { + warning (OPT_Wpsabi, "ABI for flattened empty union and zero " + "length array changed in GCC 16"); + warned = 1; + } + + return n_new2 > 0 ? n_new2 : 0; +} + +struct riscv_aggregate_field_info_t { + unsigned num_fpr; + unsigned num_gpr; + + riscv_aggregate_field_info_t () + : num_fpr (0), num_gpr (0) + {} +}; + +static riscv_aggregate_field_info_t +riscv_parse_aggregate_field_info (riscv_aggregate_field *fields, int n) +{ + riscv_aggregate_field_info_t info; + for (int i = 0; i < n; i++) + { + info.num_fpr += SCALAR_FLOAT_TYPE_P (fields[i].type); + info.num_gpr += INTEGRAL_TYPE_P (fields[i].type); + } + + return info; } /* See whether TYPE is a record whose fields should be returned in one or @@ -6084,35 +6193,48 @@ riscv_pass_aggregate_in_fpr_and_gpr_p (const_tree type, static int warned = 0; /* This is the old ABI, which differs for C++ and C. */ - unsigned num_int_old = 0, num_float_old = 0; - int n_old = riscv_flatten_aggregate_argument (type, fields, false); - for (int i = 0; i < n_old; i++) - { - num_float_old += SCALAR_FLOAT_TYPE_P (fields[i].type); - num_int_old += INTEGRAL_TYPE_P (fields[i].type); - } + int n_old = riscv_flatten_aggregate_argument (type, fields, false, false); + riscv_aggregate_field_info_t old_info; + old_info = riscv_parse_aggregate_field_info (fields, n_old); /* This is the new ABI, which is the same for C++ and C. */ - unsigned num_int_new = 0, num_float_new = 0; - int n_new = riscv_flatten_aggregate_argument (type, fields, true); - for (int i = 0; i < n_new; i++) - { - num_float_new += SCALAR_FLOAT_TYPE_P (fields[i].type); - num_int_new += INTEGRAL_TYPE_P (fields[i].type); - } + int n_new = riscv_flatten_aggregate_argument (type, fields, true, false); + riscv_aggregate_field_info_t new_info; + new_info = riscv_parse_aggregate_field_info (fields, n_new); - if (((num_int_old == 1 && num_float_old == 1 - && (num_int_old != num_int_new || num_float_old != num_float_new)) - || (num_int_new == 1 && num_float_new == 1 - && (num_int_old != num_int_new || num_float_old != num_float_new))) - && (warned == 0)) + bool values_changed = old_info.num_fpr != new_info.num_fpr + || old_info.num_gpr != new_info.num_gpr; + bool old_is_one_one = old_info.num_fpr == 1 && old_info.num_gpr == 1; + bool new_is_one_one = new_info.num_fpr == 1 && new_info.num_gpr == 1; + + if (values_changed + && (old_is_one_one || new_is_one_one) + && warned == 0) { warning (OPT_Wpsabi, "ABI for flattened struct with zero-length " "bit-fields changed in GCC 10"); warned = 1; } - return num_int_new == 1 && num_float_new == 1; + /* ABI with fixing flatten empty union. */ + int n_new2 = riscv_flatten_aggregate_argument (type, fields, true, true); + riscv_aggregate_field_info_t new2_info; + new2_info = riscv_parse_aggregate_field_info (fields, n_new2); + + values_changed = new_info.num_fpr != new2_info.num_fpr + || new_info.num_gpr != new2_info.num_gpr; + bool new2_is_one_one = new2_info.num_fpr == 1 && new2_info.num_gpr == 1; + + if (values_changed + && (new_is_one_one || new2_is_one_one) + && warned == 0) + { + warning (OPT_Wpsabi, "ABI for flattened empty union and zero " + "length array changed in GCC 16"); + warned = 1; + } + + return new2_is_one_one; } /* Return the representation of an argument passed or returned in an FPR @@ -6466,7 +6588,7 @@ riscv_pass_aggregate_in_vr (struct riscv_arg_info *info, riscv_aggregate_field fields[8]; unsigned int abi_vlen = riscv_get_cc_abi_vlen (cum->variant_cc); int i; - int n = riscv_flatten_aggregate_argument (type, fields, true, + int n = riscv_flatten_aggregate_argument (type, fields, true, true, /* vls_p */ true, abi_vlen); if (n == -1) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index c713451..1e88a60 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -103,13 +103,12 @@ (define_code_attr m_float [(float "float") (unsigned_float "ufloat")]) (define_code_attr s_float [(float "") (unsigned_float "uns")]) -;; This iterator and attribute allow FP-to-integer rounding of two types +;; This iterator and attribute allow FP-to-integer rounding of three types ;; to be generated from one template. -(define_int_iterator ANY_ROUND [UNSPEC_CEIL UNSPEC_FLOOR UNSPEC_ROUND]) +(define_int_iterator ANY_ROUND [UNSPEC_CEIL UNSPEC_FLOOR + (UNSPEC_ROUND "flag_unsafe_math_optimizations")]) (define_int_attr m_round [(UNSPEC_CEIL "ceil") (UNSPEC_FLOOR "floor") (UNSPEC_ROUND "round")]) -(define_int_attr c_round [(UNSPEC_CEIL "1") (UNSPEC_FLOOR "1") - (UNSPEC_ROUND "flag_unsafe_math_optimizations")]) ;; Attributes. @@ -1174,7 +1173,7 @@ (define_insn "l<m_round>sfsi2" [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(match_operand:SF 1 "register_operand" "f")] ANY_ROUND))] - "TARGET_HARD_FLOAT && <c_round>" + "TARGET_HARD_FLOAT" "<m_round>.s\t%0, %1, 0" [(set_attr "type" "fconv") (set_attr "mode" "SF") @@ -1184,7 +1183,7 @@ [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(plus:SF (match_operand:SF 1 "register_operand" "f") (match_dup 1))] ANY_ROUND))] - "TARGET_HARD_FLOAT && <c_round>" + "TARGET_HARD_FLOAT" "<m_round>.s\t%0, %1, 1" [(set_attr "type" "fconv") (set_attr "mode" "SF") @@ -1194,7 +1193,7 @@ [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(mult:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "fix_scaling_operand" ""))] ANY_ROUND))] - "TARGET_HARD_FLOAT && <c_round>" + "TARGET_HARD_FLOAT" "<m_round>.s\t%0, %1, %U2" [(set_attr "type" "fconv") (set_attr "mode" "SF") diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ddcd552..08d1fa7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2025-11-02 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/122421 + * module.cc (trees_in::read_var_def): Don't handle class-scope + variables anymore. + (trees_in::read_class_def): Handle them here instead. + 2025-11-01 Nathaniel Shead <nathanieloshead@gmail.com> PR c++/122381 diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index e0b9efa..e9cacf1 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -8996,11 +8996,14 @@ trees_in::decl_value () dump (dumper::TREE) && dump ("CDTOR %N is %scloned", decl, cloned_p ? "" : "not "); if (cloned_p) - build_cdtor_clones (decl, flags & 2, flags & 4, - /* Update the member vec, if there is - one (we're in a different cluster - to the class defn). */ - CLASSTYPE_MEMBER_VEC (DECL_CONTEXT (decl))); + { + /* Update the member vec, if there is one (we're in a different + cluster to the class defn) and this isn't a primary template + specialization (as in tsubst_function_decl). */ + bool up = (CLASSTYPE_MEMBER_VEC (DECL_CONTEXT (decl)) + && !primary_template_specialization_p (decl)); + build_cdtor_clones (decl, flags & 2, flags & 4, up); + } } } @@ -17246,13 +17249,16 @@ module_state::write_namespaces (elf_out *to, vec<depset *> spaces, flags |= 4; if (DECL_MODULE_EXPORT_P (ns)) flags |= 8; + if (TREE_DEPRECATED (ns)) + flags |= 16; dump () && dump ("Writing namespace:%u %N%s%s%s%s", b->cluster, ns, flags & 1 ? ", public" : "", flags & 2 ? ", inline" : "", flags & 4 ? ", purview" : "", - flags & 8 ? ", export" : ""); + flags & 8 ? ", export" : "", + flags & 16 ? ", deprecated" : ""); sec.u (b->cluster); sec.u (to->name (DECL_NAME (ns))); write_namespace (sec, b->deps[0]); @@ -17328,7 +17334,8 @@ module_state::read_namespaces (unsigned num) flags & 1 ? ", public" : "", flags & 2 ? ", inline" : "", flags & 4 ? ", purview" : "", - flags & 8 ? ", export" : ""); + flags & 8 ? ", export" : "", + flags & 16 ? ", deprecated" : ""); bool visible_p = ((flags & 8) || ((flags & 1) && (flags & 4) @@ -17349,6 +17356,9 @@ module_state::read_namespaces (unsigned num) DECL_MODULE_EXPORT_P (inner) = true; } + if (flags & 16) + TREE_DEPRECATED (inner) = true; + if (tags) DECL_ATTRIBUTES (inner) = tree_cons (get_identifier ("abi_tag"), tags, DECL_ATTRIBUTES (inner)); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 30eae4b..7427825 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3471,12 +3471,41 @@ Function Attributes}, @ref{PowerPC Function Attributes}, @ref{ARM Function Attributes}, @ref{AArch64 Function Attributes}, and @ref{S/390 Function Attributes} for details. +On targets supporting @code{target} function multiversioning (x86), when using +C++, you can declare multiple functions with the same signatures but different +@code{target} attribute values, and the correct version is chosen by the +dynamic linker. In the example below, two function versions are produced +with differing mangling. Additionally an ifunc resolver is created to +select the correct version to populate the @code{func} symbol. + +@smallexample +int func (void) __attribute__ ((target ("arch=core2"))) @{ return 1; @} +int func (void) __attribute__ ((target ("sse3"))) @{ return 2; @} +@end smallexample + +Declarations annotated with @code{target} cannot be used in combination with +declarations annotated with @code{target_clones} in a single multiversioned +function definition. + +@xref{Function Multiversioning} for more details. + +@cindex @code{target_version} function attribute +@item target_version (@var{option}) +On targets with @code{target_version} function multiversioning (AArch64 and +RISC-V) in C or C++, you can declare multiple functions with +@code{target_version} or @code{target_clones} attributes to define a function +version set. + +@xref{Function Multiversioning} for more details. + @cindex @code{target_clones} function attribute @item target_clones (@var{options}) The @code{target_clones} attribute is used to specify that a function be cloned into multiple versions compiled with different target options -than specified on the command line. The supported options and restrictions -are the same as for @code{target} attribute. +than specified on the command line. + +For the x86 and PowerPC targets, the supported options and restrictions +are the same as for the @code{target} attribute. For instance, on an x86, you could compile a function with @code{target_clones("sse4.1,avx")}. GCC creates two function clones, @@ -3488,16 +3517,20 @@ function clones, one compiled with @option{-mcpu=power9} and another with the default options. GCC must be configured to use GLIBC 2.23 or newer in order to use the @code{target_clones} attribute. -It also creates a resolver function (see -the @code{ifunc} attribute above) that dynamically selects a clone -suitable for current architecture. The resolver is created only if there -is a usage of a function with @code{target_clones} attribute. +@code{target_clones} works similarly for targets that support the +@code{target_version} attribute (AArch64 and RISC-V). The attribute takes +multiple arguments, and generates a versioned clone for each. A function +annotated with @code{target_clones} is equivalent to the same function +duplicated for each valid version string in the argument, where each +version is instead annotated with @code{target_version}. This means that a +@code{target_clones} annotated function definition can be used in combination +with @code{target_version} annotated functions definitions and other +@code{target_clones} annotated function definitions. -Note that any subsequent call of a function without @code{target_clone} -from a @code{target_clone} caller will not lead to copying -(target clone) of the called function. -If you want to enforce such behavior, -we recommend declaring the calling function with the @code{flatten} attribute? +For these targets the supported options and restrictions are the same as for +the @code{target_version} attribute. + +@xref{Function Multiversioning} for more details. @cindex @code{unavailable} function attribute @item unavailable @@ -19701,7 +19734,16 @@ into the data cache. The instruction is issued in slot I1@. These built-in functions are available for LoongArch. -Data Type Description: +@menu +* Data Types:: +* Directly-mapped Builtin Functions:: +* Directly-mapped Division Builtin Functions:: +* Other Builtin Functions:: +@end menu + +@node Data Types +@subsubsection Data Types + @itemize @item @code{imm0_31}, a compile-time constant in range 0 to 31; @item @code{imm0_16383}, a compile-time constant in range 0 to 16383; @@ -19709,6 +19751,9 @@ Data Type Description: @item @code{imm_n2048_2047}, a compile-time constant in range -2048 to 2047; @end itemize +@node Directly-mapped Builtin Functions +@subsubsection Directly-mapped Builtin Functions + The intrinsics provided are listed below: @smallexample unsigned int __builtin_loongarch_movfcsr2gr (imm0_31) @@ -19832,6 +19877,9 @@ function you need to include @code{larchintrin.h}. void __break (imm0_32767) @end smallexample +@node Directly-mapped Division Builtin Functions +@subsubsection Directly-mapped Division Builtin Functions + These intrinsic functions are available by including @code{larchintrin.h} and using @option{-mfrecipe}. @smallexample @@ -19841,6 +19889,9 @@ using @option{-mfrecipe}. double __frsqrte_d (double); @end smallexample +@node Other Builtin Functions +@subsubsection Other Builtin Functions + Additional built-in functions are available for LoongArch family processors to efficiently use 128-bit floating-point (__float128) values. @@ -19867,6 +19918,15 @@ GCC provides intrinsics to access the LSX (Loongson SIMD Extension) instructions The interface is made available by including @code{<lsxintrin.h>} and using @option{-mlsx}. +@menu +* SX Data Types:: +* Directly-mapped SX Builtin Functions:: +* Directly-mapped SX Division Builtin Functions:: +@end menu + +@node SX Data Types +@subsubsection SX Data Types + The following vectors typedefs are included in @code{lsxintrin.h}: @itemize @@ -19894,6 +19954,9 @@ input/output values manipulated: @item @code{imm_n2048_2047}, an integer literal in range -2048 to 2047. @end itemize +@node Directly-mapped SX Builtin Functions +@subsubsection Directly-mapped SX Builtin Functions + For convenience, GCC defines functions @code{__lsx_vrepli_@{b/h/w/d@}} and @code{__lsx_b[n]z_@{v/b/h/w/d@}}, which are implemented as follows: @@ -20677,6 +20740,9 @@ __m128i __lsx_vxori_b (__m128i, imm0_255); __m128i __lsx_vxor_v (__m128i, __m128i); @end smallexample +@node Directly-mapped SX Division Builtin Functions +@subsubsection Directly-mapped SX Division Builtin Functions + These intrinsic functions are available by including @code{lsxintrin.h} and using @option{-mfrecipe} and @option{-mlsx}. @smallexample @@ -20693,6 +20759,16 @@ GCC provides intrinsics to access the LASX (Loongson Advanced SIMD Extension) instructions. The interface is made available by including @code{<lasxintrin.h>} and using @option{-mlasx}. +@menu +* ASX Data Types:: +* Directly-mapped ASX Builtin Functions:: +* Directly-mapped ASX Division Builtin Functions:: +* Directly-mapped SX and ASX Conversion Builtin Functions:: +@end menu + +@node ASX Data Types +@subsubsection ASX Data Types + The following vectors typedefs are included in @code{lasxintrin.h}: @itemize @@ -20721,6 +20797,9 @@ input/output values manipulated: @item @code{imm_n2048_2047}, an integer literal in range -2048 to 2047. @end itemize +@node Directly-mapped ASX Builtin Functions +@subsubsection Directly-mapped ASX Builtin Functions + For convenience, GCC defines functions @code{__lasx_xvrepli_@{b/h/w/d@}} and @code{__lasx_b[n]z_@{v/b/h/w/d@}}, which are implemented as follows: @@ -21525,6 +21604,9 @@ __m256i __lasx_xvxori_b (__m256i, imm0_255); __m256i __lasx_xvxor_v (__m256i, __m256i); @end smallexample +@node Directly-mapped ASX Division Builtin Functions +@subsubsection Directly-mapped ASX Division Builtin Functions + These intrinsic functions are available by including @code{lasxintrin.h} and using @option{-mfrecipe} and @option{-mlasx}. @smallexample @@ -21534,6 +21616,213 @@ __m256d __lasx_xvfrsqrte_d (__m256d); __m256 __lasx_xvfrsqrte_s (__m256); @end smallexample +@node Directly-mapped SX and ASX Conversion Builtin Functions +@subsubsection Directly-mapped SX and ASX Conversion Builtin Functions + +For convenience, the @code{lsxintrin.h} file was imported into @code{ +lasxintrin.h} and 18 new interface functions for 128 and 256 vector +conversions were added, using the @option{-mlasx} option. +@smallexample +__m256 __lasx_cast_128_s (__m128); +__m256d __lasx_cast_128_d (__m128d); +__m256i __lasx_cast_128 (__m128i); +__m256 __lasx_concat_128_s (__m128, __m128); +__m256d __lasx_concat_128_d (__m128d, __m128d); +__m256i __lasx_concat_128 (__m128i, __m128i); +__m128 __lasx_extract_128_lo_s (__m256); +__m128 __lasx_extract_128_hi_s (__m256); +__m128d __lasx_extract_128_lo_d (__m256d); +__m128d __lasx_extract_128_hi_d (__m256d); +__m128i __lasx_extract_128_lo (__m256i); +__m128i __lasx_extract_128_hi (__m256i); +__m256 __lasx_insert_128_lo_s (__m256, __m128); +__m256 __lasx_insert_128_hi_s (__m256, __m128); +__m256d __lasx_insert_128_lo_d (__m256d, __m128d); +__m256d __lasx_insert_128_hi_d (__m256d, __m128d); +__m256i __lasx_insert_128_lo (__m256i, __m128i); +__m256i __lasx_insert_128_hi (__m256i, __m128i); +@end smallexample + +When gcc does not support interfaces for 128 and 256 conversions, +use the following code for equivalent substitution. + +@smallexample + + #ifndef __loongarch_asx_sx_conv + + #include <lasxintrin.h> + #include <lsxintrin.h> + __m256 inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_cast_128_s (__m128 src) + @{ + __m256 dest; + asm ("" : "=f"(dest) : "0"(src)); + return dest; + @} + + __m256d inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_cast_128_d (__m128d src) + @{ + __m256d dest; + asm ("" : "=f"(dest) : "0"(src)); + return dest; + @} + + __m256i inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_cast_128 (__m128i src) + @{ + __m256i dest; + asm ("" : "=f"(dest) : "0"(src)); + return dest; + @} + + __m256 inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_concat_128_s (__m128 src1, __m128 src2) + @{ + __m256 dest; + asm ("xvpermi.q %u0,%u2,0x02\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m256d inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_concat_128_d (__m128d src1, __m128d src2) + @{ + __m256d dest; + asm ("xvpermi.q %u0,%u2,0x02\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m256i inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_concat_128 (__m128i src1, __m128i src2) + @{ + __m256i dest; + asm ("xvpermi.q %u0,%u2,0x02\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m128 inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_extract_128_lo_s (__m256 src) + @{ + __m128 dest; + asm ("" : "=f"(dest) : "0"(src)); + return dest; + @} + + __m128d inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_extract_128_lo_d (__m256d src) + @{ + __m128d dest; + asm ("" : "=f"(dest) : "0"(src)); + return dest; + @} + + __m128i inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_extract_128_lo (__m256i src) + @{ + __m128i dest; + asm ("" : "=f"(dest) : "0"(src)); + return dest; + @} + + __m128 inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_extract_128_hi_s (__m256 src) + @{ + __m128 dest; + asm ("xvpermi.d %u0,%u1,0xe\n" + : "=f"(dest) + : "f"(src)); + return dest; + @} + + __m128d inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_extract_128_hi_d (__m256d src) + @{ + __m128d dest; + asm ("xvpermi.d %u0,%u1,0xe\n" + : "=f"(dest) + : "f"(src)); + return dest; + @} + + __m128i inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_extract_128_hi (__m256i src) + @{ + __m128i dest; + asm ("xvpermi.d %u0,%u1,0xe\n" + : "=f"(dest) + : "f"(src)); + return dest; + @} + + __m256 inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_insert_128_lo_s (__m256 src1, __m128 src2) + @{ + __m256 dest; + asm ("xvpermi.q %u0,%u2,0x30\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m256d inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_insert_128_lo_d (__m256d a, __m128d b) + @{ + __m256d dest; + asm ("xvpermi.q %u0,%u2,0x30\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m256i inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_insert_128_lo (__m256i src1, __m128i src2) + @{ + __m256i dest; + asm ("xvpermi.q %u0,%u2,0x30\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m256 inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_insert_128_hi_s (__m256 src1, __m128 src2) + @{ + __m256 dest; + asm ("xvpermi.q %u0,%u2,0x02\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m256d inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_insert_128_hi_d (__m256d src1, __m128d src2) + @{ + __m256d dest; + asm ("xvpermi.q %u0,%u2,0x02\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + + __m256i inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __lasx_insert_128_hi (__m256i src1, __m128i src2) + @{ + __m256i dest; + asm ("xvpermi.q %u0,%u2,0x02\n" + : "=f"(dest) + : "0"(src1), "f"(src2)); + return dest; + @} + #endif + +@end smallexample + @node MIPS DSP Built-in Functions @subsection MIPS DSP Built-in Functions @@ -30682,11 +30971,79 @@ For the effects of the @code{hot} attribute on functions, see @section Function Multiversioning @cindex function versions -With the GNU C++ front end, for x86 targets, you may specify multiple -versions of a function, where each function is specialized for a -specific target feature. At runtime, the appropriate version of the -function is automatically executed depending on the characteristics of -the execution platform. Here is an example. +Function multiversioning is a mechanism that enables compiling multiple +versions of a function, each specialized for different combinations of +architecture extensions. Additionally, the compiler generates a resolver that +the dynamic linker uses to detect architecture support and choose the +appropriate version at runtime. + +Function multiversioning relies on the indirect function extension to the ELF +standard, and therefore Binutils version 2.20.1 or higher and GNU C Library +version 2.11.1 are required to use this feature. + +There are two versions of function multiversioning supported by GCC. + +For targets supporting the @code{target_version} attribute (AArch64 and RISC-V), +when compiling for C or C++, a function version set can be defined by a +combination of function definitions with @code{target_version} and +@code{target_clones} attributes, across translation units. + +For example: + +@smallexample +// fmv.h: +int foo (); +int foo [[gnu::target_clones("sve", "sve2")]] (); +int foo [[gnu::target_version("dotprod;priority=1")]] (); + +// fmv1.cc +#include "fmv.h" + +int foo () +@{ + // The default version of foo. + return 0; +@} + +// fmv2.cc: +#include "fmv.h" + +int foo [[gnu::target_clones("sve", "sve2")]] () +@{ + // foo versions for sve and sve2 + return 1; +@} + +int foo [[gnu::target_version("dotprod")]] () +@{ + // foo version for dotprod extension + return 2; +@} + +// main.cc +#include "fmv.h" + +int main () +@{ + int (*p)() = &foo; + assert ((*p) () == foo ()); + return 0; +@} +@end smallexample + +This example results in 4 versions of the foo function being generated, and +a resolver which is used by the dynamic linker to choose the correct version. + +For the AArch64 target GCC implements function multiversionsing, with the +semantics and version strings as specified in the +@ref{ARM C Language Extensions (ACLE)}. + +For targets that support multiversioning with the @code{target} attribute +(x86) a multiversioned function can be defined with either multiple function +definitions with the @code{target} attribute (in C++) within a translation unit, +or a single definition with the @code{target_clones} attribute. + +Here is an example. @smallexample __attribute__ ((target ("default"))) diff --git a/gcc/gimple.cc b/gcc/gimple.cc index 102e21f..b968a45 100644 --- a/gcc/gimple.cc +++ b/gcc/gimple.cc @@ -2283,6 +2283,28 @@ gimple_copy (gimple *stmt) } } + switch (gimple_code (stmt)) + { + case GIMPLE_OMP_ATOMIC_LOAD: + { + gomp_atomic_load *g = as_a <gomp_atomic_load *> (copy); + gimple_omp_atomic_load_set_lhs (g, + unshare_expr (gimple_omp_atomic_load_lhs (g))); + gimple_omp_atomic_load_set_rhs (g, + unshare_expr (gimple_omp_atomic_load_rhs (g))); + break; + } + case GIMPLE_OMP_ATOMIC_STORE: + { + gomp_atomic_store *g = as_a <gomp_atomic_store *> (copy); + gimple_omp_atomic_store_set_val (g, + unshare_expr (gimple_omp_atomic_store_val (g))); + break; + } + default: + break; + } + /* Make copy of operands. */ for (i = 0; i < num_ops; i++) gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i))); diff --git a/gcc/m2/ChangeLog b/gcc/m2/ChangeLog index bb307bb..737ab12 100644 --- a/gcc/m2/ChangeLog +++ b/gcc/m2/ChangeLog @@ -1,3 +1,36 @@ +2025-11-02 Gaius Mulley <gaiusmod2@gmail.com> + + PR modula2/122499 + * gm2-compiler/M2StackSpell.mod (PushName): Add comment. + (GetSpellHint): Rewrite. + (GetExportedSpellHint): New procedure function. + (GetScopeSpellHint): New procedure function. + * gm2-compiler/P1Build.bnf (IdentScope): Rewrite. + (PossiblyExportIdent): Ditto. + * gm2-compiler/P1SymBuild.mod (BuildImportInnerModule): Add + parameter to AddNameToImportList. + * gm2-compiler/SymbolTable.def (GetUnknownOnImport): New + procedure function. + (GetUnknownDeclScope): Ditto. + (AddNameToScope): Add tok parameter. + (AddNameToImportList): Ditto. + * gm2-compiler/SymbolTable.mod (SymUndefined): New field + declScope. + New field onImport. + (MakeObject): Add tok parameter. + (FillInUnknownFields): Initialize declScope. + Initialize onImport. + (GetUnknownOnImport): New procedure function. + (GetUnknownDeclScope): Ditto. + (AddNameToScope): Pass tok to MakeObject. + (AddNameToImportList): Add tok parameter. + Pass tok to MakeObject. + (GetDeclaredSym): Add parameters to FillInUnknownFields. + (RequestSym): Ditto. + (FetchUnknownFromModule): Ditto. + (FetchUnknownFromDefImp): Ditto. + (FetchUnknownFrom): Ditto. + 2025-10-30 Gaius Mulley <gaiusmod2@gmail.com> PR modula2/122485 diff --git a/gcc/m2/gm2-compiler/M2StackSpell.mod b/gcc/m2/gm2-compiler/M2StackSpell.mod index ac58c1c..06ce923 100644 --- a/gcc/m2/gm2-compiler/M2StackSpell.mod +++ b/gcc/m2/gm2-compiler/M2StackSpell.mod @@ -23,8 +23,10 @@ IMPLEMENTATION MODULE M2StackSpell ; FROM SymbolTable IMPORT NulSym, IsModule, IsDefImp, IsRecord, IsEnumeration, IsProcedure, GetNth, - GetSymName, GetSym, GetLocalSym, - UnknownReported, + GetSymName, GetSym, GetLocalSym, GetScope, + UnknownReported, IsUnknown, + GetUnknownOnImport, GetUnknownDeclScope, + ForeachExportedDo, ForeachProcedureDo, ForeachLocalSymDo, ForeachFieldEnumerationDo ; @@ -179,8 +181,9 @@ VAR PushCount : CARDINAL ; PushCandidate: Candidates ; + (* - PushName - + PushName - push a name to the candidate vec. *) PROCEDURE PushName (sym: CARDINAL) ; @@ -279,7 +282,7 @@ BEGIN cand := m2spellcheck.InitCandidates () ; IF PushCandidates (cand, sym) > 1 THEN - content := m2spellcheck.FindClosestCharStar (cand, string (misspelt)) ; + content := m2spellcheck.FindClosestCharStar (cand, string (misspelt)) ELSE content := NIL END ; @@ -310,6 +313,52 @@ END AddPunctuation ; *) PROCEDURE GetSpellHint (unknown: CARDINAL) : String ; +BEGIN + IF IsUnknown (unknown) AND + GetUnknownOnImport (unknown) AND + (GetUnknownDeclScope (unknown) # GetScope (unknown)) + THEN + (* It was created during an import statement. *) + RETURN GetExportedSpellHint (unknown, GetUnknownDeclScope (unknown)) + END ; + RETURN GetScopeSpellHint (unknown) +END GetSpellHint ; + + +(* + GetExportedSpellHint - return a string describing a spelling hint + using the module exported identifiers. +*) + +PROCEDURE GetExportedSpellHint (unknown, module: CARDINAL) : String ; +VAR + content : ConstCharStar ; + misspell, + HintStr : String ; +BEGIN + misspell := InitStringCharStar (KeyToCharStar (GetSymName (unknown))) ; + HintStr := NIL ; + PushCount := 0 ; + PushCandidate := m2spellcheck.InitCandidates () ; + ForeachExportedDo (module, PushName) ; + ForeachLocalSymDo (module, PushName) ; + IF PushCount > 0 + THEN + content := m2spellcheck.FindClosestCharStar (PushCandidate, + string (misspell)) ; + HintStr := BuildHintStr (HintStr, content) + END ; + m2spellcheck.KillCandidates (PushCandidate) ; + RETURN AddPunctuation (HintStr, '?') +END GetExportedSpellHint ; + + +(* + GetScopeSpellHint - return a string describing a spelling hint + using the visible scopes. +*) + +PROCEDURE GetScopeSpellHint (unknown: CARDINAL) : String ; VAR i, n : CARDINAL ; sym : CARDINAL ; @@ -331,7 +380,7 @@ BEGIN INC (i) END ; RETURN AddPunctuation (HintStr, '?') -END GetSpellHint ; +END GetScopeSpellHint ; (* diff --git a/gcc/m2/gm2-compiler/P1Build.bnf b/gcc/m2/gm2-compiler/P1Build.bnf index 4cbdf17..d56a286 100644 --- a/gcc/m2/gm2-compiler/P1Build.bnf +++ b/gcc/m2/gm2-compiler/P1Build.bnf @@ -358,9 +358,12 @@ END Ident ; *) PROCEDURE IdentScope (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ; +VAR + tokpos: CARDINAL ; BEGIN - Ident(stopset0, stopset1, stopset2) ; - AddNameToScope(LastIdent) + tokpos := GetTokenNo () ; + Ident (stopset0, stopset1, stopset2) ; + AddNameToScope (tokpos, LastIdent) END IdentScope ; @@ -374,14 +377,14 @@ PROCEDURE PossiblyExportIdent (stopset0: SetOfStop0; stopset1: SetOfStop1; stops VAR nothing: CARDINAL ; BEGIN - AddNameToScope(makekey(currentstring)) ; - PushTFtok(makekey(currentstring), identtok, GetTokenNo()) ; + AddNameToScope (GetTokenNo (), makekey (currentstring)) ; + PushTFtok (makekey (currentstring), identtok, GetTokenNo ()) ; CheckExplicitExported ; - IF NOT IsAutoPushOn() + IF NOT IsAutoPushOn () THEN - PopT(nothing) + PopT (nothing) END ; - Expect(identtok, stopset0, stopset1, stopset2) + Expect (identtok, stopset0, stopset1, stopset2) END PossiblyExportIdent ; diff --git a/gcc/m2/gm2-compiler/P1SymBuild.mod b/gcc/m2/gm2-compiler/P1SymBuild.mod index d6c0f2f..33d12bd 100644 --- a/gcc/m2/gm2-compiler/P1SymBuild.mod +++ b/gcc/m2/gm2-compiler/P1SymBuild.mod @@ -39,6 +39,7 @@ FROM M2Reserved IMPORT ImportTok, ExportTok, QualifiedTok, UnQualifiedTok, FROM FifoQueue IMPORT PutEnumerationIntoFifoQueue ; FROM P0SymBuild IMPORT EnterBlock, LeaveBlock ; +FROM libc IMPORT printf ; FROM SymbolTable IMPORT NulSym, ModeOfAddr, @@ -472,9 +473,6 @@ BEGIN OperandT(n+1)) ; i := 1 ; WHILE i<=n DO -(* - WriteString('Importing ') ; WriteKey(Operand(j)) ; WriteString(' from ') ; WriteKey(GetSymName(ModSym)) ; WriteLn ; -*) Sym := GetExported (OperandTok (n+1-i), ModSym, OperandT (n+1-i)) ; PutImported (Sym) ; @@ -619,7 +617,7 @@ BEGIN (* Ident List contains list of objects *) i := 1 ; WHILE i<=n DO - AddNameToImportList (OperandT (i)) ; + AddNameToImportList (OperandTok (i), OperandT (i)) ; INC (i) END ELSE diff --git a/gcc/m2/gm2-compiler/SymbolTable.def b/gcc/m2/gm2-compiler/SymbolTable.def index 09a5590..2a2f201 100644 --- a/gcc/m2/gm2-compiler/SymbolTable.def +++ b/gcc/m2/gm2-compiler/SymbolTable.def @@ -2136,6 +2136,20 @@ PROCEDURE UnknownReported (sym: CARDINAL) ; (* + GetUnknownOnImport - returns the onimport field of unknown sym. +*) + +PROCEDURE GetUnknownOnImport (sym: CARDINAL) : BOOLEAN ; + + +(* + GetUnknownDeclScope - returns the decl scope of unknown sym. +*) + +PROCEDURE GetUnknownDeclScope (sym: CARDINAL) : CARDINAL ; + + +(* IsReallyPointer - returns TRUE is sym is a pointer, address or a type declared as a pointer or address. *) @@ -2613,7 +2627,7 @@ PROCEDURE ResolveConstructorTypes ; current scope. *) -PROCEDURE AddNameToScope (n: Name) ; +PROCEDURE AddNameToScope (tok: CARDINAL; n: Name) ; (* @@ -2621,7 +2635,7 @@ PROCEDURE AddNameToScope (n: Name) ; module. *) -PROCEDURE AddNameToImportList (n: Name) ; +PROCEDURE AddNameToImportList (tok: CARDINAL; n: Name) ; (* diff --git a/gcc/m2/gm2-compiler/SymbolTable.mod b/gcc/m2/gm2-compiler/SymbolTable.mod index 023bd49..25170fb 100644 --- a/gcc/m2/gm2-compiler/SymbolTable.mod +++ b/gcc/m2/gm2-compiler/SymbolTable.mod @@ -230,6 +230,10 @@ TYPE SymUndefined = RECORD name : Name ; (* Index into name array, name *) (* of record. *) + declScope : CARDINAL ; (* Scope where unknown is *) + (* created. *) + onImport : BOOLEAN ; (* Was it created during an *) + (* import? *) oafamily : CARDINAL ; (* The oafamily for this sym *) errorScope: ErrorScope ; (* Title scope used if an *) (* error is emitted. *) @@ -1591,7 +1595,7 @@ END IsError ; MakeObject - creates an object node. *) -PROCEDURE MakeObject (name: Name) : CARDINAL ; +PROCEDURE MakeObject (tok: CARDINAL; name: Name) : CARDINAL ; VAR pSym: PtrToSymbol ; Sym : CARDINAL ; @@ -1601,8 +1605,8 @@ BEGIN WITH pSym^ DO SymbolType := ObjectSym ; Object.name := name ; - InitWhereDeclared(Object.At) ; - InitWhereFirstUsed(Object.At) + InitWhereDeclaredTok (tok, Object.At) ; + InitWhereFirstUsedTok (tok, Object.At) END ; RETURN( Sym ) END MakeObject ; @@ -8647,7 +8651,7 @@ BEGIN THEN (* Make unknown *) NewSym (Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ; (* Add to unknown tree *) AddSymToUnknownTree (ScopePtr, SymName, Sym) (* @@ -8684,7 +8688,7 @@ BEGIN THEN (* Make unknown. *) NewSym (Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ; (* Add to unknown tree *) AddSymToUnknownTree (ScopePtr, SymName, Sym) (* @@ -9252,7 +9256,7 @@ BEGIN IF Sym=NulSym THEN NewSym (Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, ModSym, TRUE) ; PutSymKey (Unresolved, SymName, Sym) END END @@ -9283,7 +9287,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, ModSym, TRUE) ; PutSymKey (Unresolved, SymName, Sym) END END @@ -9310,7 +9314,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, scope, TRUE) ; PutSymKey(Unresolved, SymName, Sym) END END | @@ -9319,7 +9323,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, scope, TRUE) ; PutSymKey(Unresolved, SymName, Sym) END END | @@ -9328,7 +9332,7 @@ BEGIN IF Sym=NulSym THEN NewSym(Sym) ; - FillInUnknownFields (tok, Sym, SymName) ; + FillInUnknownFields (tok, Sym, SymName, NulSym, FALSE) ; PutSymKey(Unresolved, SymName, Sym) END END @@ -9599,7 +9603,8 @@ BEGIN CheckForUnknowns (tokno, name, ExportUnQualifiedTree, 'EXPORT UNQUALIFIED') ; CheckForSymbols (ExportRequest, - 'requested by another modules import (symbols have not been exported by the appropriate definition module)') ; + 'requested by another module import' + + ' and the symbol has not been exported by the appropriate definition module') ; CheckForUnknowns (tokno, name, Unresolved, 'unresolved') ; CheckForUnknowns (tokno, name, LocalSymbols, 'locally used') END | @@ -9752,12 +9757,12 @@ PROCEDURE CheckForSymbols (Tree: SymbolTree; a: ARRAY OF CHAR) ; VAR s: String ; BEGIN - IF NOT IsEmptyTree(Tree) + IF DoesTreeContainAny (Tree, IsUnreportedUnknown) THEN s := InitString ("the symbols are unknown at the end of module {%1Ea} when ") ; s := ConCat (s, Mark(InitString(a))) ; MetaErrorString1 (s, MainModule) ; - ForeachNodeDo(Tree, SymbolError) + ForeachNodeDo (Tree, SymbolError) END END CheckForSymbols ; @@ -11708,10 +11713,11 @@ END IsProcedureAnyNoReturn ; (* - FillInUnknownFields - + FillInUnknownFields - fills in all fields for the undefined sym. *) -PROCEDURE FillInUnknownFields (tok: CARDINAL; sym: CARDINAL; SymName: Name) ; +PROCEDURE FillInUnknownFields (tok: CARDINAL; sym: CARDINAL; SymName: Name; + descscope: CARDINAL; onimport: BOOLEAN) ; VAR pSym: PtrToSymbol ; BEGIN @@ -11722,6 +11728,8 @@ BEGIN name := SymName ; oafamily := NulSym ; errorScope := GetCurrentErrorScope () ; + declScope := descscope ; + onImport := onimport ; InitWhereFirstUsedTok (tok, At) END END @@ -11729,6 +11737,34 @@ END FillInUnknownFields ; (* + GetUnknownOnImport - returns the onimport field of unknown sym. +*) + +PROCEDURE GetUnknownOnImport (sym: CARDINAL) : BOOLEAN ; +VAR + pSym: PtrToSymbol ; +BEGIN + Assert (IsUnknown (sym)) ; + pSym := GetPsym (sym) ; + RETURN pSym^.Undefined.onImport +END GetUnknownOnImport ; + + +(* + GetUnknownDeclScope - returns the decl scope of unknown sym. +*) + +PROCEDURE GetUnknownDeclScope (sym: CARDINAL) : CARDINAL ; +VAR + pSym: PtrToSymbol ; +BEGIN + Assert (IsUnknown (sym)) ; + pSym := GetPsym (sym) ; + RETURN pSym^.Undefined.declScope +END GetUnknownDeclScope ; + + +(* FillInPointerFields - given a new symbol, sym, make it a pointer symbol and initialize its fields. *) @@ -12985,7 +13021,7 @@ END AddNameTo ; current scope. *) -PROCEDURE AddNameToScope (n: Name) ; +PROCEDURE AddNameToScope (tok: CARDINAL; n: Name) ; VAR pSym : PtrToSymbol ; scope: CARDINAL ; @@ -12995,9 +13031,9 @@ BEGIN WITH pSym^ DO CASE SymbolType OF - ProcedureSym: AddNameTo(Procedure.NamedObjects, MakeObject(n)) | - ModuleSym : AddNameTo(Module.NamedObjects, MakeObject(n)) | - DefImpSym : AddNameTo(DefImp.NamedObjects, MakeObject(n)) + ProcedureSym: AddNameTo(Procedure.NamedObjects, MakeObject (tok, n)) | + ModuleSym : AddNameTo(Module.NamedObjects, MakeObject (tok, n)) | + DefImpSym : AddNameTo(DefImp.NamedObjects, MakeObject (tok, n)) ELSE InternalError ('expecting - DefImp') @@ -13011,7 +13047,7 @@ END AddNameToScope ; module. *) -PROCEDURE AddNameToImportList (n: Name) ; +PROCEDURE AddNameToImportList (tok: CARDINAL; n: Name) ; VAR pSym : PtrToSymbol ; scope: CARDINAL ; @@ -13021,8 +13057,8 @@ BEGIN WITH pSym^ DO CASE SymbolType OF - ModuleSym: AddNameTo(Module.NamedImports, MakeObject(n)) | - DefImpSym: AddNameTo(DefImp.NamedImports, MakeObject(n)) + ModuleSym: AddNameTo (Module.NamedImports, MakeObject (tok, n)) | + DefImpSym: AddNameTo (DefImp.NamedImports, MakeObject (tok, n)) ELSE InternalError ('expecting - DefImp or Module symbol') diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index b9591eb..989cf9c 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -6451,6 +6451,21 @@ simplify_context::simplify_relational_operation_1 (rtx_code code, /* Canonicalize (LEU x 0) as (EQ x 0). */ if (code == LEU) return simplify_gen_relational (EQ, mode, cmp_mode, op0, op1); + + if ((code == NE || code == EQ) + /* Verify op0 is IOR */ + && GET_CODE (op0) == IOR + /* only enters if op1 is 0 */ + /* Verify IOR operand is NE */ + && GET_CODE (XEXP (op0, 0)) == NE + /* Verfiy second NE operand is 0 */ + && XEXP (XEXP (op0, 0), 1) == CONST0_RTX (mode)) + { + rtx t = gen_rtx_IOR (mode, XEXP (XEXP (op0, 0), 0), XEXP (op0, 1)); + t = gen_rtx_fmt_ee (code, mode, t, CONST0_RTX (mode)); + return t; + } + } else if (op1 == const1_rtx) { diff --git a/gcc/symtab.cc b/gcc/symtab.cc index fb2aca5..3dbfad3 100644 --- a/gcc/symtab.cc +++ b/gcc/symtab.cc @@ -882,7 +882,7 @@ static const char * const toplevel_type_names[] = "variable", }; -static_assert (ARRAY_SIZE(toplevel_type_names)==TOPLEVEL_MAX); +static_assert (ARRAY_SIZE(toplevel_type_names) == TOPLEVEL_MAX, ""); /* Dump the visibility of the symbol. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 91ec37f..452c9c9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,49 @@ +2025-11-02 Gaius Mulley <gaiusmod2@gmail.com> + + PR modula2/122499 + * gm2.dg/spell/iso/fail/badimport2.mod: New test. + * gm2.dg/spell/iso/fail/badimport3.mod: New test. + * gm2.dg/spell/iso/fail/badimport4.mod: New test. + +2025-11-02 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.target/sparc/small-struct-1.c: Run only on Solaris. + +2025-11-02 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.target/sparc/cbcond-1.c: Accept reverse branches. + * gcc.target/sparc/cbcond-2.c: Likewise. + * gcc.target/sparc/overflow-3.c: Likewise. + * gcc.target/sparc/overflow-4.c: Likewise. + * gcc.target/sparc/overflow-5.c: Likewise. + +2025-11-02 Uros Bizjak <ubizjak@gmail.com> + + PR target/122518 + * gcc.target/i386/pr122518.c: New test. + +2025-11-02 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/specs/unknown_discr1.ads: New test. + * gnat.dg/specs/unknown_discr1_pkg.ads: New helper. + * gnat.dg/specs/unknown_discr1_pkg-child.ads: Likewise. + * gnat.dg/specs/unknown_discr1_pkg-g.ads: Likewise. + * gnat.dg/specs/unknown_discr1_pkg-inst.ads: Likewise. + +2025-11-02 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/use_type4.adb: New test. + +2025-11-02 Georg-Johann Lay <avr@gjlay.de> + + * gcc.target/avr/torture/pr84211-fuse-move-1.c: Add -fno-lto. + +2025-11-02 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/122421 + * g++.dg/modules/inst-6_a.C: New test. + * g++.dg/modules/inst-6_b.C: New test. + 2025-11-01 Shreya Munnangi <smunnangi1@ventanamicro.com> PR target/67731 diff --git a/gcc/testsuite/g++.dg/abi/param2.C b/gcc/testsuite/g++.dg/abi/param2.C index d28387a..4752717 100644 --- a/gcc/testsuite/g++.dg/abi/param2.C +++ b/gcc/testsuite/g++.dg/abi/param2.C @@ -1,7 +1,7 @@ // PR target/20795 // Test passing aligned empty aggregate // { dg-do compile } -// { dg-options "-Wno-psabi" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } +// { dg-options "-Wno-psabi" { target { { { i?86-*-* x86_64-*-* } && ilp32 } || { riscv*-*-* } } } } struct S { union {} a; } __attribute__((aligned)); diff --git a/gcc/testsuite/g++.dg/modules/clone-5_a.C b/gcc/testsuite/g++.dg/modules/clone-5_a.C new file mode 100644 index 0000000..4a72e8f --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/clone-5_a.C @@ -0,0 +1,25 @@ +// Test that a random instantiation of a constructor template doesn't end up in +// the overload set for other arguments. + +// { dg-do compile { target c++20 } } +// { dg-additional-options "-fmodules" } + +export module M; + +export { + inline int i; + + template <class T> + struct A { + A(const T* p, unsigned long len) { ++i; } + template <class B, class E> + requires (!__is_convertible(E,unsigned long)) + A(B,E) { ++i; } + }; + + inline void f() + { + const char *const p = nullptr; + A<char> a (p, p); // instantiate A<const char *, const char *> + } +} diff --git a/gcc/testsuite/g++.dg/modules/clone-5_b.C b/gcc/testsuite/g++.dg/modules/clone-5_b.C new file mode 100644 index 0000000..f66b465 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/clone-5_b.C @@ -0,0 +1,9 @@ +// { dg-additional-options -fmodules } + +import M; + +int main() +{ + const char *const p = nullptr; + A<char> (p, 0); +} diff --git a/gcc/testsuite/g++.dg/modules/namespace-15_a.C b/gcc/testsuite/g++.dg/modules/namespace-15_a.C new file mode 100644 index 0000000..7c0c0e6 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/namespace-15_a.C @@ -0,0 +1,9 @@ +// Test that namespace deprecation is represented in the gcm. + +// { dg-additional-options "-fmodules" } + +export module M; + +export { + namespace [[deprecated]] N { } +} diff --git a/gcc/testsuite/g++.dg/modules/namespace-15_b.C b/gcc/testsuite/g++.dg/modules/namespace-15_b.C new file mode 100644 index 0000000..5128e82 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/namespace-15_b.C @@ -0,0 +1,5 @@ +// { dg-additional-options -fmodules } + +import M; + +using namespace N; // { dg-warning "deprecated" } diff --git a/gcc/testsuite/g++.target/aarch64/mv-cpu-features.C b/gcc/testsuite/g++.target/aarch64/mv-cpu-features.C index ad6accd..56e2916 100644 --- a/gcc/testsuite/g++.target/aarch64/mv-cpu-features.C +++ b/gcc/testsuite/g++.target/aarch64/mv-cpu-features.C @@ -41,6 +41,14 @@ int impl () #define _IFUNC_ARG_HWCAP (1ULL << 62) #endif +#ifndef HWCAP_ATOMICS +#define HWCAP_ATOMICS (1 << 8) +#endif + +#ifndef HWCAP2_RNG +#define HWCAP2_RNG (1 << 16) +#endif + extern "C" void __init_cpu_features_resolver (unsigned long hwcap, const ifunc_arg_t *arg); diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-1.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-1.cc new file mode 100644 index 0000000..69a1350 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-1.cc @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Su2e_1f { + union { + struct { + } e1, e2; + } u; + float f; +}; +struct Su2e_1f echo_Su2e_1f(int i, float f, struct Su2e_1f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-2.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-2.cc new file mode 100644 index 0000000..763477c --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-2.cc @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Su2e_2f { + union { + struct { + } e1, e2; + } u; + float f; + float g; +}; +struct Su2e_2f echo_Su2e_2f(int i, float f, struct Su2e_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+8 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+8 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-3.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-3.cc new file mode 100644 index 0000000..5c9ce31 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-3.cc @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smu2e_1f { + union { + struct { + } e1, e2; + } u1; + struct { + float f; + union { + struct { + } e1, e2; + } u; + } ue; + union { + struct { + } e1, e2; + } u2; +}; +struct Smu2e_1f echo_Smu2e_1f(int i, float f, struct Smu2e_1f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-4.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-4.cc new file mode 100644 index 0000000..ecefc94 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct+union-4.cc @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smu2e_2f { + union { + struct { + } e1, e2; + } u1; + struct { + float f; + float g; + union { + struct { + } e1, e2; + } u; + } ue; + union { + struct { + } e1, e2; + } u2; +}; +struct Smu2e_2f echo_Smu2e_2f(int i, float f, struct Smu2e_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+8 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+8 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-1.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-1.cc new file mode 100644 index 0000000..81f563e --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-1.cc @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Se_1f { + struct { + } e1; + float f; +}; +struct Se_1f echo_Se_1f(int i, float f, struct Se_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-10.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-10.cc new file mode 100644 index 0000000..167f54c --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-10.cc @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S1ae_2f { + struct { + } e1[1]; + float f; + float g; +}; +struct S1ae_2f echo_S1ae_2f(int i, float f, struct S1ae_2f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(mem.*:DI .*\[.* s\+0 .*\]\)[[:space:]]+\(reg.*:DI \d+ a1\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(mem.*:DI .*\[.* s\+8 .*\]\)[[:space:]]+\(reg.*:DI \d+ a2\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:DI \d+ a0 .*\)[[:space:]]+\(subreg:DI \(reg.*:TI \d+ \[ <retval> \]\) 0\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:DI \d+ a1 .*\)[[:space:]]+\(subreg:DI \(reg.*:TI \d+ \[ <retval> \]\) 8\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-11.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-11.cc new file mode 100644 index 0000000..057994d --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-11.cc @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm1ae_1f { + struct { + } e1[1]; + struct { + float f; + struct { + } e[1]; + } fe; + struct { + } e2[1]; +}; +struct Sm1ae_1f echo_Sm1ae_1f(int i, float f, struct Sm1ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(mem.*:DI .*\[.* s\+0 .*\]\)[[:space:]]+\(reg.*:DI \d+ a1\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(mem.*:DI .*\[.* s\+8 .*\]\)[[:space:]]+\(reg.*:DI \d+ a2\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:DI \d+ a0 .*\)[[:space:]]+\(subreg:DI \(reg.*:TI \d+ \[ <retval> \]\) 0\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:DI \d+ a1 .*\)[[:space:]]+\(subreg:DI \(reg.*:TI \d+ \[ <retval> \]\) 8\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-12.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-12.cc new file mode 100644 index 0000000..d8f0154 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-12.cc @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm1ae_2f { + struct { + } e1[1]; + struct { + float f; + float g; + struct { + } e[1]; + } fe; + struct { + } e2[1]; +}; +struct Sm1ae_2f echo_Sm1ae_2f(int i, float f, struct Sm1ae_2f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\[.* \.result_ptr\+0 .*\]} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-2.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-2.cc new file mode 100644 index 0000000..9d5669c --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-2.cc @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Se_2f { + struct { + } e1; + float f; + float g; +}; +struct Se_2f echo_Se_2f(int i, float f, struct Se_2f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+8 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+8 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-3.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-3.cc new file mode 100644 index 0000000..7b9e71a --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-3.cc @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sme_1f { + struct { + } e1; + struct { + float f; + struct { + } e; + } fe; + struct { + } e2; +}; +struct Sme_1f echo_Sme_1f(int i, float f, struct Sme_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-4.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-4.cc new file mode 100644 index 0000000..aaec892 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-4.cc @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sme_2f { + struct { + } e1; + struct { + float f; + float g; + struct { + } e; + } fe; + struct { + } e2; +}; +struct Sme_2f echo_Sme_2f(int i, float f, struct Sme_2f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+8 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+8 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-5.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-5.cc new file mode 100644 index 0000000..0ae1e41 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-5.cc @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S0ae_1f { + struct { + } e1[0]; + float f; +}; +struct S0ae_1f echo_S0ae_1f(int i, float f, struct S0ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-6.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-6.cc new file mode 100644 index 0000000..d3d0b65 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-6.cc @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S0ae_2f { + struct { + } e1[0]; + float f; + float g; +}; +struct S0ae_2f echo_S0ae_2f(int i, float f, struct S0ae_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-7.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-7.cc new file mode 100644 index 0000000..9eae13d --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-7.cc @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm0ae_1f { + struct { + } e1[0]; + struct { + float f; + struct { + } e[0]; + } fe; + struct { + } e2[0]; +}; +struct Sm0ae_1f echo_Sm0ae_1f(int i, float f, struct Sm0ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-8.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-8.cc new file mode 100644 index 0000000..e7c81f4 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-8.cc @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm0ae_2f { + struct { + } e1[0]; + struct { + float f; + float g; + struct { + } e[0]; + } fe; + struct { + } e2[0]; +}; +struct Sm0ae_2f echo_Sm0ae_2f(int i, float f, struct Sm0ae_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-struct-9.cc b/gcc/testsuite/g++.target/riscv/abi/empty-struct-9.cc new file mode 100644 index 0000000..d36d50b --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-struct-9.cc @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S1ae_1f { + struct { + } e1[1]; + float f; +}; +struct S1ae_1f echo_S1ae_1f(int i, float f, struct S1ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(mem.*:DI .*\[.* s\+0 .*\]\)[[:space:]]+\(reg.*:DI \d+ a1\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:DI \d+ a0\)[[:space:]]+\(reg.*:DI \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-union-1.cc b/gcc/testsuite/g++.target/riscv/abi/empty-union-1.cc new file mode 100644 index 0000000..e3c2376 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-union-1.cc @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Seu_1f { + union { + } e1; + float f; +}; +struct Seu_1f echo_Seu_1f(int i, float f, struct Seu_1f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-union-2.cc b/gcc/testsuite/g++.target/riscv/abi/empty-union-2.cc new file mode 100644 index 0000000..d7b7d05 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-union-2.cc @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S2eu_2f { + union { + } e1; + float f; + float g; +}; +struct S2eu_2f echo_S2eu_2f(int i, float f, struct S2eu_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+8 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+8 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-union-3.cc b/gcc/testsuite/g++.target/riscv/abi/empty-union-3.cc new file mode 100644 index 0000000..f12af7a --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-union-3.cc @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smeu_1f { + union { + } e1; + struct { + float f; + union { + } e; + } fe; + union { + } e2; +}; +struct Smeu_1f echo_Smeu_1f(int i, float f, struct Smeu_1f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/abi/empty-union-4.cc b/gcc/testsuite/g++.target/riscv/abi/empty-union-4.cc new file mode 100644 index 0000000..ab8c56e --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/abi/empty-union-4.cc @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smeu_2f { + union { + } e1; + struct { + float f; + float g; + union { + } e; + } fe; + union { + } e2; +}; +struct Smeu_2f echo_Smeu_2f(int i, float f, struct Smeu_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+8 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+8 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/riscv.exp b/gcc/testsuite/g++.target/riscv/riscv.exp index f58e688..e268bd8 100644 --- a/gcc/testsuite/g++.target/riscv/riscv.exp +++ b/gcc/testsuite/g++.target/riscv/riscv.exp @@ -29,6 +29,7 @@ dg-init # Main loop. dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" "" +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/abi/*.cc]] "" "" # All done. dg-finish diff --git a/gcc/testsuite/gcc.dg/compat/pr83487-1_x.c b/gcc/testsuite/gcc.dg/compat/pr83487-1_x.c index b5b208f..22b71cf 100644 --- a/gcc/testsuite/gcc.dg/compat/pr83487-1_x.c +++ b/gcc/testsuite/gcc.dg/compat/pr83487-1_x.c @@ -1,4 +1,5 @@ /* { dg-options "-fno-common" { target { hppa*-*-hpux* } } } */ +/* { dg-options "-Wno-psabi" { target { riscv*-*-* } } } */ #include "pr83487-1.h" extern diff --git a/gcc/testsuite/gcc.dg/compat/pr83487-1_y.c b/gcc/testsuite/gcc.dg/compat/pr83487-1_y.c index ad336dd..cf275d8 100644 --- a/gcc/testsuite/gcc.dg/compat/pr83487-1_y.c +++ b/gcc/testsuite/gcc.dg/compat/pr83487-1_y.c @@ -1,4 +1,5 @@ /* { dg-options "-fno-common" { target { hppa*-*-hpux* } } } */ +/* { dg-options "-Wno-psabi" { target { riscv*-*-* } } } */ #include "pr83487-1.h" struct A a; diff --git a/gcc/testsuite/gcc.dg/compat/pr83487-2_x.c b/gcc/testsuite/gcc.dg/compat/pr83487-2_x.c index 7103194..399ac86 100644 --- a/gcc/testsuite/gcc.dg/compat/pr83487-2_x.c +++ b/gcc/testsuite/gcc.dg/compat/pr83487-2_x.c @@ -1,3 +1,4 @@ /* { dg-options "-fno-common" { target { hppa*-*-hpux* } } } */ +/* { dg-options "-Wno-psabi" { target { riscv*-*-* } } } */ #define PR83487_LARGE #include "pr83487-1_x.c" diff --git a/gcc/testsuite/gcc.dg/compat/pr83487-2_y.c b/gcc/testsuite/gcc.dg/compat/pr83487-2_y.c index e176783..dc6c1f8 100644 --- a/gcc/testsuite/gcc.dg/compat/pr83487-2_y.c +++ b/gcc/testsuite/gcc.dg/compat/pr83487-2_y.c @@ -1,3 +1,4 @@ /* { dg-options "-fno-common" { target { hppa*-*-hpux* } } } */ +/* { dg-options "-Wno-psabi" { target { riscv*-*-* } } } */ #define PR83487_LARGE #include "pr83487-1_y.c" diff --git a/gcc/testsuite/gcc.dg/torture/pr28814.c b/gcc/testsuite/gcc.dg/torture/pr28814.c index cf641ca..e835ff5 100644 --- a/gcc/testsuite/gcc.dg/torture/pr28814.c +++ b/gcc/testsuite/gcc.dg/torture/pr28814.c @@ -1,4 +1,5 @@ /* { dg-do compile { target { ilp32 || lp64 } } } */ +/* { dg-options "-Wno-psabi" { target { riscv*-*-* } } } */ struct w49 { diff --git a/gcc/testsuite/gcc.dg/vect/pr122475.c b/gcc/testsuite/gcc.dg/vect/pr122475.c new file mode 100644 index 0000000..ed229c5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr122475.c @@ -0,0 +1,13 @@ +/* { dg-additional-options "-march=armv8-a+sve" { target aarch64*-*-* } } */ +/* Check that we don't ICE. */ +int a; +int b; +int main() { + for (char t = 0; t < 14; t += 2) + for (int u = 0; u < 242; u += 4) { + a = a < 0 ? a : 0; + b = b < 0 ? b : 0; + } +} + +/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 1 "vect" { target aarch64*-*-* } } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fmv_priority.in b/gcc/testsuite/gcc.target/aarch64/fmv_priority.in index 93209bc..4637369 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmv_priority.in +++ b/gcc/testsuite/gcc.target/aarch64/fmv_priority.in @@ -30,10 +30,12 @@ int fn [[gnu::target_version("fp16")]] (int) { return 1; } int fn_fp16(int) asm("fn._Mfp16"); int fn [[gnu::target_version("fp16fml")]] (int) { return 1; } int fn_fp16fml(int) asm("fn._Mfp16fml"); -/* TODO: These FMV features are not yet supported in GCC. */ -// int fn [[gnu::target_version("dit")]] (int) { return 1; } -// int fn [[gnu::target_version("dpb")]] (int) { return 1; } -// int fn [[gnu::target_version("dpb2")]] (int) { return 1; } +int fn [[gnu::target_version("dit")]] (int) { return 1; } +int fn_dit(int) asm("fn._Mdit"); +int fn [[gnu::target_version("dpb")]] (int) { return 1; } +int fn_dpb(int) asm("fn._Mdpb"); +int fn [[gnu::target_version("dpb2")]] (int) { return 1; } +int fn_dpb2(int) asm("fn._Mdpb2"); int fn [[gnu::target_version("jscvt")]] (int) { return 1; } int fn_jscvt(int) asm("fn._Mjscvt"); int fn [[gnu::target_version("fcma")]] (int) { return 1; } @@ -68,15 +70,14 @@ int fn [[gnu::target_version("sve2-sm4")]] (int) { return 1; } int fn_sve2_sm4(int) asm("fn._Msve2_sm4"); int fn [[gnu::target_version("sve2+sme")]] (int) { return 1; } int fn_sve2_sme(int) asm("fn._Msve2Msme"); -/* TODO: This FMV features is not yet supported in GCC. */ -// int fn [[gnu::target_version("memtag")]] (int) { return 1; } +int fn [[gnu::target_version("memtag")]] (int) { return 1; } +int fn_memtag(int) asm("fn._Mmemtag"); int fn [[gnu::target_version("sb")]] (int) { return 1; } int fn_sb(int) asm("fn._Msb"); -/* TODO: This FMV feature is not yet supported in GCC. */ -// int fn [[gnu::target_version("ssbs")]] (int) { return 1; } -// int fn_ssbs(int) asm("fn._Mssbs"); -/* TODO: This FMV feature is not yet supported in GCC. */ -// int fn [[gnu::target_version("bti")]] (int) { return 1; } +int fn [[gnu::target_version("ssbs")]] (int) { return 1; } +int fn_ssbs(int) asm("fn._Mssbs"); +int fn [[gnu::target_version("bti")]] (int) { return 1; } +int fn_bti(int) asm("fn._Mbti"); int fn [[gnu::target_version("wfxt")]] (int) { return 1; } int fn_wfxt(int) asm("fn._Mwfxt"); int fn [[gnu::target_version("sve2+sme-f64f64")]] (int) { return 1; } diff --git a/gcc/testsuite/gcc.target/aarch64/fmv_priority1.c b/gcc/testsuite/gcc.target/aarch64/fmv_priority1.c index 942b7a7..6075ccf 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmv_priority1.c +++ b/gcc/testsuite/gcc.target/aarch64/fmv_priority1.c @@ -81,14 +81,14 @@ int main () { if(resolver() != &fn_fp16fml) return 1; setCPUFeature (FEAT_DIT); - // if(resolver() != &fn_dit) return 1; - // + if(resolver() != &fn_dit) return 1; + setCPUFeature (FEAT_DPB); - // if(resolver() != &fn_dpb) return 1; - // + if(resolver() != &fn_dpb) return 1; + setCPUFeature (FEAT_DPB2); - // if(resolver() != &fn_dpb2) return 1; - // + if(resolver() != &fn_dpb2) return 1; + setCPUFeature (FEAT_JSCVT); if (resolver () != &fn_jscvt) return 1; @@ -102,8 +102,8 @@ int main () { if (resolver () != &fn_rcpc2) return 1; setCPUFeature (FEAT_RCPC3); - // if(resolver() != &fn_rcpc3) return 1; - // + if(resolver() != &fn_rcpc3) return 1; + setCPUFeature (FEAT_FRINTTS); if (resolver () != &fn_frintts) return 1; @@ -141,16 +141,16 @@ int main () { if (resolver () != &fn_sve2_sme) return 1; setCPUFeature(FEAT_MEMTAG2); - // if(resolver() != &fn_memtag) return 1; + if(resolver() != &fn_memtag) return 1; setCPUFeature (FEAT_SB); if (resolver () != &fn_sb) return 1; setCPUFeature(FEAT_SSBS2); - // if(resolver() != &fn_ssbs) return 1; + if(resolver() != &fn_ssbs) return 1; setCPUFeature(FEAT_BTI); - // if(resolver() != &fn_bti) return 1; + if(resolver() != &fn_bti) return 1; setCPUFeature (FEAT_WFXT); if (resolver () != &fn_wfxt) return 1; diff --git a/gcc/testsuite/gcc.target/aarch64/fmv_priority2.c b/gcc/testsuite/gcc.target/aarch64/fmv_priority2.c index dbeb15e..9464015 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmv_priority2.c +++ b/gcc/testsuite/gcc.target/aarch64/fmv_priority2.c @@ -14,7 +14,9 @@ /* { dg-final { scan-ipa-dump-times "fn\._Msm4/\[0-9\]+\\nfn\._MrdmaMrdm/\[0-9\]+\\nfn\._Mcrc/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Mcrc/\[0-9\]+\\nfn\._Msha2/\[0-9\]+\\nfn\._Msha3/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Msha3/\[0-9\]+\\nfn\._Maes/\[0-9\]+\\nfn\._Mfp16/\[0-9\]+\\n" 1 "targetclone1" } } */ -/* { dg-final { scan-ipa-dump-times "fn\._Mfp16/\[0-9\]+\\nfn\._Mfp16fml/\[0-9\]+\\nfn\._Mjscvt/\[0-9\]+\\n" 1 "targetclone1" } } */ +/* { dg-final { scan-ipa-dump-times "fn\._Mfp16/\[0-9\]+\\nfn\._Mfp16fml/\[0-9\]+\\nfn\._Mdit/\[0-9\]+\\n" 1 "targetclone1" } } */ +/* { dg-final { scan-ipa-dump-times "fn\._Mdit/\[0-9\]+\\nfn\._Mdpb/\[0-9\]+\\nfn\._Mdpb2/\[0-9\]+\\n" 1 "targetclone1" } } */ +/* { dg-final { scan-ipa-dump-times "fn\._Mdpb2/\[0-9\]+\\nfn\._Mjscvt/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Mjscvt/\[0-9\]+\\nfn\._Mfcma/\[0-9\]+\\nfn\._Mrcpc/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Mrcpc/\[0-9\]+\\nfn\._Mrcpc2/\[0-9\]+\\nfn\._Mrcpc3/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Mrcpc3/\[0-9\]+\\nfn\._Mfrintts/\[0-9\]+\\nfn\._Mi8mm/\[0-9\]+\\n" 1 "targetclone1" } } */ @@ -23,7 +25,9 @@ /* { dg-final { scan-ipa-dump-times "fn\._Mf64mm/\[0-9\]+\\nfn\._Msve2/\[0-9\]+\\nfn\._Msve2_aes/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Msve2_aes/\[0-9\]+\\nfn\._Msve2_bitperm/\[0-9\]+\\nfn\._Msve2_sha3/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Msve2_sha3/\[0-9\]+\\nfn\._Msve2_sm4/\[0-9\]+\\nfn\._Msve2Msme/\[0-9\]+\\n" 1 "targetclone1" } } */ -/* { dg-final { scan-ipa-dump-times "fn\._Msve2Msme/\[0-9\]+\\nfn\._Msb/\[0-9\]+\\nfn\._Mwfxt/\[0-9\]+\\n" 1 "targetclone1" } } */ +/* { dg-final { scan-ipa-dump-times "fn\._Msve2Msme/\[0-9\]+\\nfn\._Mmemtag/\[0-9\]+\\nfn\._Msb/\[0-9\]+\\n" 1 "targetclone1" } } */ +/* { dg-final { scan-ipa-dump-times "fn\._Msb/\[0-9\]+\\nfn\._Mssbs/\[0-9\]+\\nfn\._Mbti/\[0-9\]+\\n" 1 "targetclone1" } } */ +/* { dg-final { scan-ipa-dump-times "fn\._Mbti/\[0-9\]+\\nfn\._Mwfxt/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Mwfxt/\[0-9\]+\\nfn\._Msve2Msme_f64f64/\[0-9\]+\\nfn\._Msve2Msme_i16i64/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Msve2Msme_i16i64/\[0-9\]+\\nfn\._Msve2Msme2/\[0-9\]+\\nfn\._Mmops/\[0-9\]+\\n" 1 "targetclone1" } } */ /* { dg-final { scan-ipa-dump-times "fn\._Mmops/\[0-9\]+\\nfn\._Mcssc/\[0-9\]+\\n" 1 "targetclone1" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-reduc-bool-19.c b/gcc/testsuite/gcc.target/aarch64/sve/vect-reduc-bool-19.c new file mode 100644 index 0000000..6492c44 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-reduc-bool-19.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-mautovec-preference=sve-only -fdump-tree-vect-details -O3 --param vect-epilogues-nomask=0" } */ + +int p[128]; + +bool __attribute__((noipa)) +fand (int n, bool r1, bool r2) +{ + bool r = true; + for (int i = 0; i < (n/2); i+=2) + { + r &= (p[i] != 0) & r1; + r &= (p[i+1] != 0) & r2; + } + return r; +} +/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-reduc-bool-20.c b/gcc/testsuite/gcc.target/aarch64/sve/vect-reduc-bool-20.c new file mode 100644 index 0000000..83c5c20 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-reduc-bool-20.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-mautovec-preference=sve-only -fdump-tree-vect-details -O3 --param vect-epilogues-nomask=0" } */ + +#include <stdbool.h> +#include <stdint.h> + +void vec_slp_cmp (char* restrict a, char* restrict b, int n) { + bool x0 = b[0] != 0; + bool x1 = b[1] != 0; + bool x2 = b[2] != 0; + bool x3 = b[3] != 0; + for (int i = 0; i < n; ++i) { + x0 &= (a[i * 4] != 0); + x1 &= (a[i * 4 + 1] != 0); + x2 &= (a[i * 4 + 2] != 0); + x3 &= (a[i * 4 + 3] != 0); + } + b[0] = x0; + b[1] = x1; + b[2] = x2; + b[3] = x3; +} + +void vec_slp_cmp1 (char* restrict a, char* restrict b, int n) { + bool x0 = b[0] != 0; + for (int i = 0; i < n; ++i) { + x0 &= (a[i] != 0); + } + b[0] = x0; +} + +/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" { target aarch64*-*-* } } } */ diff --git a/gcc/testsuite/gcc.target/arc/movv2hi-be.c b/gcc/testsuite/gcc.target/arc/movv2hi-be.c new file mode 100644 index 0000000..7d4b8e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/movv2hi-be.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +typedef short v2hi __attribute__((vector_size(4))); + +__attribute__((noinline)) void foo3(short a) +{ + if (a != 520) + { + __builtin_abort(); + } +} + +__attribute__((noinline)) void foo2(v2hi v) +{ + foo3(v[0]); +} + +__attribute__((noinline)) void foo(v2hi *v) +{ + foo2(*v); +} + +int main (void) +{ + v2hi v; + v[0] = 520; + v[1] = -1; + foo(&v); + foo2(v); + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/pr92606.c b/gcc/testsuite/gcc.target/avr/torture/pr92606.c index a391d7e..99d1ca6 100644 --- a/gcc/testsuite/gcc.target/avr/torture/pr92606.c +++ b/gcc/testsuite/gcc.target/avr/torture/pr92606.c @@ -14,10 +14,10 @@ typedef uint32_t T; { \ uint16_t __addr16 = (uint16_t)(X); \ uint32_t __result; \ - __asm__ __volatile__ ("lpm %A0, Z+" "\n\t" \ - "lpm %B0, Z+" "\n\t" \ - "lpm %C0, Z+" "\n\t" \ - "lpm %D0, Z" "\n\t" \ + __asm__ __volatile__ ("lpm $ mov %A0,r0 $ adiw %1,1" "\n\t" \ + "lpm $ mov %B0,r0 $ adiw %1,1" "\n\t" \ + "lpm $ mov %C0,r0 $ adiw %1,1" "\n\t" \ + "lpm $ mov %D0,r0" \ : "=r" (__result), "+z" (__addr16)); \ __result; \ })) diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-10.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-10.c new file mode 100644 index 0000000..43d6489 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-10.c @@ -0,0 +1,105 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove: +**.LFB0: +** .cfi_startproc +** cmpq \$63, %rdx +** ja .L12 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L12: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$128, %rdx +** jbe .L13 +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L6 +** je .L1 +** movdqu -16\(%rax,%rdx\), %xmm7 +** movdqu -32\(%rax,%rdx\), %xmm6 +** movdqu -48\(%rax,%rdx\), %xmm5 +** movdqu -64\(%rax,%rdx\), %xmm4 +**.L7: +** movdqu \(%rax\), %xmm3 +** subq \$64, %rsi +** addq \$64, %rcx +** addq \$64, %rax +** movdqu -48\(%rax\), %xmm2 +** movdqu -32\(%rax\), %xmm1 +** movdqu -16\(%rax\), %xmm0 +** movups %xmm3, -64\(%rcx\) +** movups %xmm2, -48\(%rcx\) +** movups %xmm1, -32\(%rcx\) +** movups %xmm0, -16\(%rcx\) +** cmpq \$64, %rsi +** ja .L7 +** movups %xmm7, -16\(%rdi,%rdx\) +** movups %xmm6, -32\(%rdi,%rdx\) +** movups %xmm5, -48\(%rdi,%rdx\) +** movups %xmm4, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** movdqu \(%rsi\), %xmm7 +** movdqu 16\(%rsi\), %xmm6 +** movdqu 32\(%rsi\), %xmm5 +** movdqu 48\(%rsi\), %xmm4 +** movdqu -16\(%rsi,%rdx\), %xmm3 +** movdqu -32\(%rsi,%rdx\), %xmm2 +** movdqu -48\(%rsi,%rdx\), %xmm1 +** movdqu -64\(%rsi,%rdx\), %xmm0 +** movups %xmm7, \(%rdi\) +** movups %xmm6, 16\(%rdi\) +** movups %xmm5, 32\(%rdi\) +** movups %xmm4, 48\(%rdi\) +** movups %xmm3, -16\(%rdi,%rdx\) +** movups %xmm2, -32\(%rdi,%rdx\) +** movups %xmm1, -48\(%rdi,%rdx\) +** movups %xmm0, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movdqu \(%rax\), %xmm3 +** movdqu 16\(%rax\), %xmm2 +** leaq \(%rdi,%rdx\), %rcx +** movdqu 32\(%rax\), %xmm1 +** movdqu 48\(%rax\), %xmm0 +** addq %rdx, %rax +**.L8: +** movdqu -16\(%rax\), %xmm7 +** movdqu -32\(%rax\), %xmm6 +** subq \$64, %rsi +** subq \$64, %rcx +** movdqu -48\(%rax\), %xmm5 +** movdqu -64\(%rax\), %xmm4 +** subq \$64, %rax +** movups %xmm7, 48\(%rcx\) +** movups %xmm6, 32\(%rcx\) +** movups %xmm5, 16\(%rcx\) +** movups %xmm4, \(%rcx\) +** cmpq \$64, %rsi +** ja .L8 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, 32\(%rdi\) +** movups %xmm0, 48\(%rdi\) +** ret +** .cfi_endproc +**... +*/ + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n >= 64) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-11a.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-11a.c new file mode 100644 index 0000000..3f4e2ca --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-11a.c @@ -0,0 +1,79 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_xmm: +**.LFB0: +** .cfi_startproc +** movq %rdi, %rax +** movl \$512, %edx +** cmpq %rdi, %rsi +** jb .L5 +** je .L1 +** movdqu 496\(%rsi\), %xmm7 +** movdqu 480\(%rsi\), %xmm6 +** movdqu 464\(%rsi\), %xmm5 +** movdqu 448\(%rsi\), %xmm4 +**.L6: +** movdqu \(%rsi\), %xmm3 +** movdqu 16\(%rsi\), %xmm2 +** subl \$64, %edx +** addq \$64, %rax +** movdqu 32\(%rsi\), %xmm1 +** movdqu 48\(%rsi\), %xmm0 +** addq \$64, %rsi +** movups %xmm3, -64\(%rax\) +** movups %xmm2, -48\(%rax\) +** movups %xmm1, -32\(%rax\) +** movups %xmm0, -16\(%rax\) +** cmpl \$64, %edx +** ja .L6 +** movups %xmm7, 496\(%rdi\) +** movups %xmm6, 480\(%rdi\) +** movups %xmm5, 464\(%rdi\) +** movups %xmm4, 448\(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movdqu \(%rsi\), %xmm7 +** movdqu 16\(%rsi\), %xmm6 +** leaq 512\(%rdi\), %rax +** addq \$512, %rsi +** movdqu -480\(%rsi\), %xmm5 +** movdqu -464\(%rsi\), %xmm4 +**.L7: +** movdqu -16\(%rsi\), %xmm3 +** subl \$64, %edx +** subq \$64, %rax +** subq \$64, %rsi +** movdqu 32\(%rsi\), %xmm2 +** movdqu 16\(%rsi\), %xmm1 +** movdqu \(%rsi\), %xmm0 +** movups %xmm3, 48\(%rax\) +** movups %xmm2, 32\(%rax\) +** movups %xmm1, 16\(%rax\) +** movups %xmm0, \(%rax\) +** cmpl \$64, %edx +** ja .L7 +** movups %xmm7, \(%rdi\) +** movups %xmm6, 16\(%rdi\) +** movups %xmm5, 32\(%rdi\) +** movups %xmm4, 48\(%rdi\) +**.L1: +** ret +** .cfi_endproc +**... +*/ + +#ifndef gcc_memmove +#define gcc_memmove gcc_memmove_xmm +#endif + +void +gcc_memmove (void *a, void *b) +{ + __builtin_memmove (a, b, 512); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-11b.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-11b.c new file mode 100644 index 0000000..031dd12 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-11b.c @@ -0,0 +1,74 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx512f -march=x86-64-v3 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_ymm: +**.LFB0: +** .cfi_startproc +** movq %rdi, %rax +** movl \$512, %edx +** cmpq %rdi, %rsi +** jb .L5 +** je .L10 +** vmovdqu 480\(%rsi\), %ymm7 +** vmovdqu 448\(%rsi\), %ymm6 +** vmovdqu 416\(%rsi\), %ymm5 +** vmovdqu 384\(%rsi\), %ymm4 +**.L6: +** vmovdqu \(%rsi\), %ymm3 +** vmovdqu 32\(%rsi\), %ymm2 +** addl \$-128, %edx +** subq \$-128, %rax +** vmovdqu 64\(%rsi\), %ymm1 +** vmovdqu 96\(%rsi\), %ymm0 +** subq \$-128, %rsi +** vmovdqu %ymm3, -128\(%rax\) +** vmovdqu %ymm2, -96\(%rax\) +** vmovdqu %ymm1, -64\(%rax\) +** vmovdqu %ymm0, -32\(%rax\) +** cmpl \$128, %edx +** ja .L6 +** vmovdqu %ymm7, 480\(%rdi\) +** vmovdqu %ymm6, 448\(%rdi\) +** vmovdqu %ymm5, 416\(%rdi\) +** vmovdqu %ymm4, 384\(%rdi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** vmovdqu \(%rsi\), %ymm7 +** vmovdqu 32\(%rsi\), %ymm6 +** leaq 512\(%rdi\), %rax +** addq \$512, %rsi +** vmovdqu -448\(%rsi\), %ymm5 +** vmovdqu -416\(%rsi\), %ymm4 +**.L7: +** vmovdqu -32\(%rsi\), %ymm3 +** addl \$-128, %edx +** addq \$-128, %rax +** addq \$-128, %rsi +** vmovdqu 64\(%rsi\), %ymm2 +** vmovdqu 32\(%rsi\), %ymm1 +** vmovdqu \(%rsi\), %ymm0 +** vmovdqu %ymm3, 96\(%rax\) +** vmovdqu %ymm2, 64\(%rax\) +** vmovdqu %ymm1, 32\(%rax\) +** vmovdqu %ymm0, \(%rax\) +** cmpl \$128, %edx +** ja .L7 +** vmovdqu %ymm7, \(%rdi\) +** vmovdqu %ymm6, 32\(%rdi\) +** vmovdqu %ymm5, 64\(%rdi\) +** vmovdqu %ymm4, 96\(%rdi\) +** vzeroupper +**.L10: +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_ymm +#include "builtin-memmove-11a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-11c.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-11c.c new file mode 100644 index 0000000..9c5e2c6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-11c.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -mmove-max=512 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { ! ia32 } } {^\t?\.} } } */ + +/* +**gcc_memmove_zmm: +**.LFB0: +** .cfi_startproc +** vmovdqu64 \(%(e|r)si\), %zmm7 +** vmovdqu64 64\(%(e|r)si\), %zmm6 +** vmovdqu64 128\(%(e|r)si\), %zmm5 +** vmovdqu64 192\(%(e|r)si\), %zmm4 +** vmovdqu64 256\(%(e|r)si\), %zmm3 +** vmovdqu64 320\(%(e|r)si\), %zmm2 +** vmovdqu64 384\(%(e|r)si\), %zmm1 +** vmovdqu64 448\(%(e|r)si\), %zmm0 +** vmovdqu64 %zmm7, \(%(e|r)di\) +** vmovdqu64 %zmm6, 64\(%(e|r)di\) +** vmovdqu64 %zmm5, 128\(%(e|r)di\) +** vmovdqu64 %zmm4, 192\(%(e|r)di\) +** vmovdqu64 %zmm3, 256\(%(e|r)di\) +** vmovdqu64 %zmm2, 320\(%(e|r)di\) +** vmovdqu64 %zmm1, 384\(%(e|r)di\) +** vmovdqu64 %zmm0, 448\(%(e|r)di\) +** vzeroupper +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_zmm +#include "builtin-memmove-11a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-12.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-12.c new file mode 100644 index 0000000..270df03 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-12.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movdqu a\+20\(%rip\), %xmm5 +** movdqu a\+36\(%rip\), %xmm4 +** movdqu a\+52\(%rip\), %xmm3 +** movdqu a\+68\(%rip\), %xmm2 +** movdqu a\+84\(%rip\), %xmm1 +** movdqu a\+100\(%rip\), %xmm0 +** movups %xmm5, a\+24\(%rip\) +** movq a\+116\(%rip\), %rax +** movdqu a\+4\(%rip\), %xmm6 +** movups %xmm4, a\+40\(%rip\) +** movl %edi, a\+4\(%rip\) +** movq %rax, a\+120\(%rip\) +** movups %xmm6, a\+8\(%rip\) +** movups %xmm3, a\+56\(%rip\) +** movups %xmm2, a\+72\(%rip\) +** movups %xmm1, a\+88\(%rip\) +** movups %xmm0, a\+104\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +#define N 32 + +int a[N]; + +void +foo (int x) +{ + __builtin_memmove (a + 2, a + 1, sizeof a - 2 * sizeof *a); + a[1] = x; +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-13.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-13.c new file mode 100644 index 0000000..1c71cce --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-13.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movl a\+3\(%rip\), %eax +** movl %eax, a\(%rip\) +** movzbl a\+7\(%rip\), %eax +** movb %al, a\+4\(%rip\) +** ret +** .cfi_endproc +**... +*/ + +char a[8] = "12345678"; + +void +foo (void) +{ + __builtin_memmove (a, a + 3, sizeof a - 3); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-14.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-14.c new file mode 100644 index 0000000..009c61d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-14.c @@ -0,0 +1,90 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove: +**.LFB0: +** .cfi_startproc +** cmpq \$64, %rdx +** jbe .L12 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L12: +** cmpl \$16, %edx +** jnb .L13 +** cmpl \$8, %edx +** jnb .L6 +** cmpl \$4, %edx +** jnb .L7 +** cmpl \$1, %edx +** ja .L8 +** jb .L1 +** movzbl \(%rsi\), %eax +** movb %al, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** cmpl \$32, %edx +** ja .L5 +** movl %edx, %edx +** movdqu \(%rsi\), %xmm1 +** movdqu -16\(%rsi,%rdx\), %xmm0 +** movups %xmm1, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movl %edx, %edx +** movdqu \(%rsi\), %xmm3 +** movdqu 16\(%rsi\), %xmm2 +** addq %rdx, %rsi +** movdqu -16\(%rsi\), %xmm1 +** movdqu -32\(%rsi\), %xmm0 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, -16\(%rdi,%rdx\) +** movups %xmm0, -32\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movl %edx, %edx +** movq \(%rsi\), %rcx +** movq -8\(%rsi,%rdx\), %rax +** movq %rcx, \(%rdi\) +** movq %rax, -8\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movl %edx, %edx +** movl \(%rsi\), %ecx +** movl -4\(%rsi,%rdx\), %eax +** movl %ecx, \(%rdi\) +** movl %eax, -4\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** movl %edx, %edx +** movzwl \(%rsi\), %ecx +** movzwl -2\(%rsi,%rdx\), %eax +** movw %cx, \(%rdi\) +** movw %ax, -2\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n <= 64) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-15.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-15.c new file mode 100644 index 0000000..c1ccf44 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-15.c @@ -0,0 +1,114 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove: +**.LFB0: +** .cfi_startproc +** cmpq \$66, %rdx +** jbe .L12 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L12: +** cmpl \$16, %edx +** jnb .L13 +** cmpl \$8, %edx +** jnb .L6 +** cmpl \$4, %edx +** jnb .L7 +** cmpl \$1, %edx +** ja .L8 +** jb .L1 +** movzbl \(%rsi\), %eax +** movb %al, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** cmpl \$32, %edx +** ja .L5 +** movl %edx, %edx +** movdqu \(%rsi\), %xmm1 +** movdqu -16\(%rsi,%rdx\), %xmm0 +** movups %xmm1, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** cmpl \$64, %edx +** jnb .L14 +** movl %edx, %edx +** movdqu \(%rsi\), %xmm3 +** movdqu 16\(%rsi\), %xmm2 +** addq %rdx, %rsi +** movdqu -16\(%rsi\), %xmm1 +** movdqu -32\(%rsi\), %xmm0 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, -16\(%rdi,%rdx\) +** movups %xmm0, -32\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movl %edx, %edx +** movq \(%rsi\), %rcx +** movq -8\(%rsi,%rdx\), %rax +** movq %rcx, \(%rdi\) +** movq %rax, -8\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L14: +** movl %edx, %edx +** movdqu \(%rsi\), %xmm7 +** movdqu 16\(%rsi\), %xmm6 +** movdqu 32\(%rsi\), %xmm5 +** movdqu 48\(%rsi\), %xmm4 +** addq %rdx, %rsi +** movdqu -16\(%rsi\), %xmm3 +** movdqu -32\(%rsi\), %xmm2 +** movdqu -48\(%rsi\), %xmm1 +** movdqu -64\(%rsi\), %xmm0 +** movups %xmm7, \(%rdi\) +** movups %xmm6, 16\(%rdi\) +** movups %xmm5, 32\(%rdi\) +** movups %xmm4, 48\(%rdi\) +** movups %xmm3, -16\(%rdi,%rdx\) +** movups %xmm2, -32\(%rdi,%rdx\) +** movups %xmm1, -48\(%rdi,%rdx\) +** movups %xmm0, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movl %edx, %edx +** movl \(%rsi\), %ecx +** movl -4\(%rsi,%rdx\), %eax +** movl %ecx, \(%rdi\) +** movl %eax, -4\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** movl %edx, %edx +** movzwl \(%rsi\), %ecx +** movzwl -2\(%rsi,%rdx\), %eax +** movw %cx, \(%rdi\) +** movw %ax, -2\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n <= 66) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-1a.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-1a.c new file mode 100644 index 0000000..3459875 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-1a.c @@ -0,0 +1,123 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { ! ia32 } } {^\t?\.} } } */ + +/* +**memmove7: +**.LFB[0-9]+: +** .cfi_startproc +** movl \(%(?:r|e)si\), %edx +** movl 3\(%(?:r|e)si\), %eax +** movl %edx, \(%(?:r|e)di\) +** movl %eax, 3\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove13: +**.LFB[0-9]+: +** .cfi_startproc +** movq \(%(?:r|e)si\), %rdx +** movq 5\(%(?:r|e)si\), %rax +** movq %rdx, \(%(?:r|e)di\) +** movq %rax, 5\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove31: +**.LFB[0-9]+: +** .cfi_startproc +** movdqu \(%(?:r|e)si\), %xmm1 +** movdqu 15\(%(?:r|e)si\), %xmm0 +** movups %xmm1, \(%(?:r|e)di\) +** movups %xmm0, 15\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove39: +**.LFB[0-9]+: +** .cfi_startproc +** movdqu \(%(?:r|e)si\), %xmm1 +** movdqu 16\(%(?:r|e)si\), %xmm0 +** movq 31\(%(?:r|e)si\), %rax +** movups %xmm0, 16\(%(?:r|e)di\) +** movups %xmm1, \(%(?:r|e)di\) +** movq %rax, 31\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove61: +**.LFB[0-9]+: +** .cfi_startproc +** movdqu \(%(?:r|e)si\), %xmm3 +** movdqu 16\(%(?:r|e)si\), %xmm2 +** movdqu 32\(%(?:r|e)si\), %xmm1 +** movdqu 45\(%(?:r|e)si\), %xmm0 +** movups %xmm3, \(%(?:r|e)di\) +** movups %xmm1, 32\(%(?:r|e)di\) +** movups %xmm2, 16\(%(?:r|e)di\) +** movups %xmm0, 45\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove69: +**.LFB[0-9]+: +** .cfi_startproc +** movdqu \(%(?:r|e)si\), %xmm3 +** movdqu 16\(%(?:r|e)si\), %xmm2 +** movdqu 32\(%(?:r|e)si\), %xmm1 +** movdqu 48\(%(?:r|e)si\), %xmm0 +** movq 61\(%(?:r|e)si\), %rax +** movups %xmm3, \(%(?:r|e)di\) +** movups %xmm0, 48\(%(?:r|e)di\) +** movups %xmm2, 16\(%(?:r|e)di\) +** movq %rax, 61\(%(?:r|e)di\) +** movups %xmm1, 32\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove93: +**.LFB[0-9]+: +** .cfi_startproc +** movdqu \(%(?:r|e)si\), %xmm5 +** movdqu 16\(%(?:r|e)si\), %xmm4 +** movdqu 32\(%(?:r|e)si\), %xmm3 +** movdqu 48\(%(?:r|e)si\), %xmm2 +** movdqu 64\(%(?:r|e)si\), %xmm1 +** movdqu 77\(%(?:r|e)si\), %xmm0 +** movups %xmm5, \(%(?:r|e)di\) +** movups %xmm4, 16\(%(?:r|e)di\) +** movups %xmm1, 64\(%(?:r|e)di\) +** movups %xmm3, 32\(%(?:r|e)di\) +** movups %xmm2, 48\(%(?:r|e)di\) +** movups %xmm0, 77\(%(?:r|e)di\) +** ret +**... +*/ + +#define TEST(n) \ + void \ + memmove##n (void *a, void *b) \ + { \ + __builtin_memmove (a, b, n); \ + } + +TEST (7) +TEST (13) +TEST (31) +TEST (39) +TEST (61) +TEST (69) +TEST (93) diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-1b.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-1b.c new file mode 100644 index 0000000..25d008c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-1b.c @@ -0,0 +1,98 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx512f -march=x86-64-v3 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { ! ia32 } } {^\t?\.} } } */ + +/* +**memmove7: +**.LFB[0-9]+: +** .cfi_startproc +** movl \(%(?:r|e)si\), %edx +** movl 3\(%(?:r|e)si\), %eax +** movl %edx, \(%(?:r|e)di\) +** movl %eax, 3\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove13: +**.LFB[0-9]+: +** .cfi_startproc +** movq \(%(?:r|e)si\), %rdx +** movq 5\(%(?:r|e)si\), %rax +** movq %rdx, \(%(?:r|e)di\) +** movq %rax, 5\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove31: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu \(%(?:r|e)si\), %xmm1 +** vmovdqu 15\(%(?:r|e)si\), %xmm0 +** vmovdqu %xmm1, \(%(?:r|e)di\) +** vmovdqu %xmm0, 15\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove39: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu \(%(?:r|e)si\), %ymm0 +** movq 31\(%(?:r|e)si\), %rax +** vmovdqu %ymm0, \(%(?:r|e)di\) +** movq %rax, 31\(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +/* +**memmove61: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu \(%(?:r|e)si\), %ymm1 +** vmovdqu 29\(%(?:r|e)si\), %ymm0 +** vmovdqu %ymm1, \(%(?:r|e)di\) +** vmovdqu %ymm0, 29\(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +/* +**memmove69: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu 32\(%(?:r|e)si\), %ymm0 +** movq 61\(%(?:r|e)si\), %rax +** vmovdqu \(%(?:r|e)si\), %ymm1 +** vmovdqu %ymm0, 32\(%(?:r|e)di\) +** movq %rax, 61\(%(?:r|e)di\) +** vmovdqu %ymm1, \(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +/* +**memmove93: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu \(%(?:r|e)si\), %ymm2 +** vmovdqu 32\(%(?:r|e)si\), %ymm1 +** vmovdqu 61\(%(?:r|e)si\), %ymm0 +** vmovdqu %ymm1, 32\(%(?:r|e)di\) +** vmovdqu %ymm2, \(%(?:r|e)di\) +** vmovdqu %ymm0, 61\(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +#include "builtin-memmove-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-1c.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-1c.c new file mode 100644 index 0000000..9eb9a39 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-1c.c @@ -0,0 +1,94 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -mmove-max=512 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { ! ia32 } } {^\t?\.} } } */ + +/* +**memmove7: +**.LFB[0-9]+: +** .cfi_startproc +** movl \(%(?:r|e)si\), %edx +** movl 3\(%(?:r|e)si\), %eax +** movl %edx, \(%(?:r|e)di\) +** movl %eax, 3\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove13: +**.LFB[0-9]+: +** .cfi_startproc +** movq \(%(?:r|e)si\), %rdx +** movq 5\(%(?:r|e)si\), %rax +** movq %rdx, \(%(?:r|e)di\) +** movq %rax, 5\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove31: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu \(%(?:r|e)si\), %xmm1 +** vmovdqu 15\(%(?:r|e)si\), %xmm0 +** vmovdqu %xmm1, \(%(?:r|e)di\) +** vmovdqu %xmm0, 15\(%(?:r|e)di\) +** ret +**... +*/ + +/* +**memmove39: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu \(%(?:r|e)si\), %ymm0 +** movq 31\(%(?:r|e)si\), %rax +** vmovdqu %ymm0, \(%(?:r|e)di\) +** movq %rax, 31\(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +/* +**memmove61: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu \(%(?:r|e)si\), %ymm1 +** vmovdqu 29\(%(?:r|e)si\), %ymm0 +** vmovdqu %ymm1, \(%(?:r|e)di\) +** vmovdqu %ymm0, 29\(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +/* +**memmove69: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu64 \(%(?:r|e)si\), %zmm0 +** movq 61\(%(?:r|e)si\), %rax +** vmovdqu64 %zmm0, \(%(?:r|e)di\) +** movq %rax, 61\(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +/* +**memmove93: +**.LFB[0-9]+: +** .cfi_startproc +** vmovdqu64 \(%(?:r|e)si\), %zmm1 +** vmovdqu 61\(%(?:r|e)si\), %ymm0 +** vmovdqu64 %zmm1, \(%(?:r|e)di\) +** vmovdqu %ymm0, 61\(%(?:r|e)di\) +** vzeroupper +** ret +**... +*/ + +#include "builtin-memmove-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-1d.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-1d.c new file mode 100644 index 0000000..ffa7575 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-1d.c @@ -0,0 +1,226 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mgeneral-regs-only -march=x86-64 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**memmove7: +**.LFB[0-9]+: +** .cfi_startproc +** movl \(%rsi\), %edx +** movl 3\(%rsi\), %eax +** movl %edx, \(%rdi\) +** movl %eax, 3\(%rdi\) +** ret +**... +*/ + +/* +**memmove13: +**.LFB[0-9]+: +** .cfi_startproc +** movq \(%rsi\), %rdx +** movq 5\(%rsi\), %rax +** movq %rdx, \(%rdi\) +** movq %rax, 5\(%rdi\) +** ret +**... +*/ + +/* +**memmove31: +**.LFB[0-9]+: +** .cfi_startproc +** movq \(%(e|r)si\), %r8 +** movq 8\(%(e|r)si\), %rcx +** movq 16\(%(e|r)si\), %rdx +** movq 23\(%(e|r)si\), %rax +** movq %r8, \(%(e|r)di\) +** movq %rdx, 16\(%(e|r)di\) +** movq %rcx, 8\(%(e|r)di\) +** movq %rax, 23\(%(e|r)di\) +** ret +**... +*/ + +/* +**memmove39: +**.LFB[0-9]+: +** .cfi_startproc +** movq \(%rsi\), %r9 +** movq 8\(%rsi\), %r8 +** movq 16\(%rsi\), %rcx +** movq 24\(%rsi\), %rdx +** movq 31\(%rsi\), %rax +** movq %r9, \(%rdi\) +** movq %rdx, 24\(%rdi\) +** movq %r8, 8\(%rdi\) +** movq %rcx, 16\(%rdi\) +** movq %rax, 31\(%rdi\) +** ret +**... +*/ + +/* +**memmove61: +**.LFB[0-9]+: +** .cfi_startproc +** movq 8\(%rsi\), %r11 +** movq 16\(%rsi\), %r10 +** pushq %rbx +** .cfi_def_cfa_offset 16 +** .cfi_offset 3, -16 +** movq 24\(%rsi\), %r9 +** movq \(%rsi\), %rbx +** movq 32\(%rsi\), %r8 +** movq 40\(%rsi\), %rcx +** movq 48\(%rsi\), %rdx +** movq 53\(%rsi\), %rax +** movq %rbx, \(%rdi\) +** movq %r11, 8\(%rdi\) +** popq %rbx +** .cfi_def_cfa_offset 8 +** movq %rdx, 48\(%rdi\) +** movq %r10, 16\(%rdi\) +** movq %r9, 24\(%rdi\) +** movq %r8, 32\(%rdi\) +** movq %rcx, 40\(%rdi\) +** movq %rax, 53\(%rdi\) +** ret +**... +*/ + +/* +**memmove69: +**.LFB5: +** .cfi_startproc +** movq 16\(%rsi\), %r11 +** movq 24\(%rsi\), %r10 +** pushq %rbp +** .cfi_def_cfa_offset 16 +** .cfi_offset 6, -16 +** movq 32\(%rsi\), %r9 +** movq \(%rsi\), %rbp +** pushq %rbx +** .cfi_def_cfa_offset 24 +** .cfi_offset 3, -24 +** movq 40\(%rsi\), %r8 +** movq 8\(%rsi\), %rbx +** movq 48\(%rsi\), %rcx +** movq 56\(%rsi\), %rdx +** movq 61\(%rsi\), %rax +** movq %rbp, \(%rdi\) +** movq %rbx, 8\(%rdi\) +** popq %rbx +** .cfi_def_cfa_offset 16 +** movq %rdx, 56\(%rdi\) +** popq %rbp +** .cfi_def_cfa_offset 8 +** movq %r11, 16\(%rdi\) +** movq %r10, 24\(%rdi\) +** movq %r9, 32\(%rdi\) +** movq %r8, 40\(%rdi\) +** movq %rcx, 48\(%rdi\) +** movq %rax, 61\(%rdi\) +** ret +**... +*/ + +/* +**memmove93: +**.LFB[0-9]+: +** .cfi_startproc +** sub(l|q) \$24, %(e|r)sp +** .cfi_def_cfa_offset 32 +** mov(l|q) %(e|r)si, %(e|r)ax +** movl \$93, %ecx +** cmp(l|q) %(e|r)di, %(e|r)si +** jb .L14 +** je .L10 +** movq %rbx, \(%(e|r)sp\) +** mov(l|q) %(e|r)di, %(e|r)dx +** movq %r14, 8\(%(e|r)sp\) +** movq %r15, 16\(%(e|r)sp\) +** .cfi_offset 3, -32 +** .cfi_offset 14, -24 +** .cfi_offset 15, -16 +** movq 85\(%(e|r)si\), %r14 +** movq 77\(%(e|r)si\), %r15 +** movq 69\(%(e|r)si\), %r10 +** movq 61\(%(e|r)si\), %r11 +**.L15: +** movq 8\(%(e|r)ax\), %r9 +** movq 16\(%(e|r)ax\), %r8 +** subl \$32, %ecx +** add(l|q) \$32, %(e|r)dx +** movq 24\(%(e|r)ax\), %rsi +** movq \(%(e|r)ax\), %rbx +** add(l|q) \$32, %(e|r)ax +** movq %r9, -24\(%(e|r)dx\) +** movq %rbx, -32\(%(e|r)dx\) +** movq %r8, -16\(%(e|r)dx\) +** movq %rsi, -8\(%(e|r)dx\) +** cmpl \$32, %ecx +** ja .L15 +** movq %r10, 69\(%(e|r)di\) +** movq \(%(e|r)sp\), %rbx +** .cfi_restore 3 +** movq %r11, 61\(%(e|r)di\) +** movq %r14, 85\(%(e|r)di\) +** movq 8\(%(e|r)sp\), %r14 +** .cfi_restore 14 +** movq %r15, 77\(%(e|r)di\) +** movq 16\(%(e|r)sp\), %r15 +** .cfi_restore 15 +**.L10: +** add(l|q) \$24, %(e|r)sp +** .cfi_remember_state +** .cfi_def_cfa_offset 8 +** ret +** .p2align 4,,10 +** .p2align 3 +**.L14: +** .cfi_restore_state +** movq %rbx, \(%(e|r)sp\) +** lea(l|q) 93\(%(e|r)di\), %(e|r)dx +** add(l|q) \$93, %(e|r)ax +** movq %r14, 8\(%(e|r)sp\) +** movq %r15, 16\(%(e|r)sp\) +** .cfi_offset 3, -32 +** .cfi_offset 14, -24 +** .cfi_offset 15, -16 +** movq \(%(e|r)si\), %r14 +** movq 8\(%(e|r)si\), %r15 +** movq 16\(%(e|r)si\), %r10 +** movq 24\(%(e|r)si\), %r11 +**.L16: +** movq -16\(%(e|r)ax\), %r9 +** movq -24\(%(e|r)ax\), %r8 +** subl \$32, %ecx +** sub(l|q) \$32, %(e|r)dx +** movq -32\(%(e|r)ax\), %rsi +** movq -8\(%(e|r)ax\), %rbx +** sub(l|q) \$32, %(e|r)ax +** movq %r9, 16\(%(e|r)dx\) +** movq %rbx, 24\(%(e|r)dx\) +** movq %r8, 8\(%(e|r)dx\) +** movq %rsi, \(%(e|r)dx\) +** cmpl \$32, %ecx +** ja .L16 +** movq %r14, \(%(e|r)di\) +** movq \(%(e|r)sp\), %rbx +** .cfi_restore 3 +** movq %r15, 8\(%(e|r)di\) +** movq 8\(%(e|r)sp\), %r14 +** .cfi_restore 14 +** movq %r10, 16\(%(e|r)di\) +** movq 16\(%(e|r)sp\), %r15 +** .cfi_restore 15 +** movq %r11, 24\(%(e|r)di\) +** add(l|q) \$24, %(e|r)sp +** .cfi_def_cfa_offset 8 +** ret +**... +*/ + +#include "builtin-memmove-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-2a.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-2a.c new file mode 100644 index 0000000..0a7e704 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-2a.c @@ -0,0 +1,165 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_xmm: +**.LFB0: +** .cfi_startproc +** movq %rdi, %rax +** movq %rsi, %rcx +** cmpq \$16, %rdx +** jb .L3 +** cmpq \$32, %rdx +** jbe .L17 +** cmpq \$128, %rdx +** jbe .L18 +** movq %rdx, %rsi +** cmpq %rdi, %rcx +** jb .L11 +** je .L2 +** movdqu -16\(%rcx,%rdx\), %xmm7 +** movdqu -32\(%rcx,%rdx\), %xmm6 +** movdqu -48\(%rcx,%rdx\), %xmm5 +** movdqu -64\(%rcx,%rdx\), %xmm4 +**.L12: +** movdqu \(%rcx\), %xmm3 +** subq \$64, %rsi +** addq \$64, %rdi +** addq \$64, %rcx +** movdqu -48\(%rcx\), %xmm2 +** movdqu -32\(%rcx\), %xmm1 +** movdqu -16\(%rcx\), %xmm0 +** movups %xmm3, -64\(%rdi\) +** movups %xmm2, -48\(%rdi\) +** movups %xmm1, -32\(%rdi\) +** movups %xmm0, -16\(%rdi\) +** cmpq \$64, %rsi +** ja .L12 +** movups %xmm7, -16\(%rax,%rdx\) +** movups %xmm6, -32\(%rax,%rdx\) +** movups %xmm5, -48\(%rax,%rdx\) +** movups %xmm4, -64\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L3: +** cmpq \$8, %rdx +** jb .L19 +** movq \(%rsi\), %rdi +** movq -8\(%rsi,%rdx\), %rcx +** movq %rdi, \(%rax\) +** movq %rcx, -8\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** cmpq \$4, %rdx +** jnb .L6 +** cmpq \$1, %rdx +** ja .L7 +** jb .L2 +** movzbl \(%rsi\), %edx +** movb %dl, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L17: +** movdqu \(%rsi\), %xmm1 +** movdqu -16\(%rsi,%rdx\), %xmm0 +** movups %xmm1, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L18: +** cmpq \$64, %rdx +** jb .L10 +** movdqu \(%rsi\), %xmm7 +** movdqu 16\(%rsi\), %xmm6 +** movdqu 32\(%rsi\), %xmm5 +** movdqu 48\(%rsi\), %xmm4 +** movdqu -16\(%rsi,%rdx\), %xmm3 +** movdqu -32\(%rsi,%rdx\), %xmm2 +** movdqu -48\(%rsi,%rdx\), %xmm1 +** movdqu -64\(%rsi,%rdx\), %xmm0 +** movups %xmm7, \(%rdi\) +** movups %xmm6, 16\(%rdi\) +** movups %xmm5, 32\(%rdi\) +** movups %xmm4, 48\(%rdi\) +** movups %xmm3, -16\(%rdi,%rdx\) +** movups %xmm2, -32\(%rdi,%rdx\) +** movups %xmm1, -48\(%rdi,%rdx\) +** movups %xmm0, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movl \(%rsi\), %edi +** movl -4\(%rsi,%rdx\), %ecx +** movl %edi, \(%rax\) +** movl %ecx, -4\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L11: +** movdqu \(%rcx\), %xmm7 +** movdqu 16\(%rcx\), %xmm6 +** leaq \(%rdi,%rdx\), %rdi +** movdqu 32\(%rcx\), %xmm5 +** movdqu 48\(%rcx\), %xmm4 +** addq %rdx, %rcx +**.L13: +** movdqu -16\(%rcx\), %xmm3 +** movdqu -32\(%rcx\), %xmm2 +** subq \$64, %rsi +** subq \$64, %rdi +** movdqu -48\(%rcx\), %xmm1 +** movdqu -64\(%rcx\), %xmm0 +** subq \$64, %rcx +** movups %xmm3, 48\(%rdi\) +** movups %xmm2, 32\(%rdi\) +** movups %xmm1, 16\(%rdi\) +** movups %xmm0, \(%rdi\) +** cmpq \$64, %rsi +** ja .L13 +** movups %xmm7, \(%rax\) +** movups %xmm6, 16\(%rax\) +** movups %xmm5, 32\(%rax\) +** movups %xmm4, 48\(%rax\) +**.L2: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L10: +** movdqu \(%rsi\), %xmm3 +** movdqu 16\(%rsi\), %xmm2 +** movdqu -16\(%rsi,%rdx\), %xmm1 +** movdqu -32\(%rsi,%rdx\), %xmm0 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, -16\(%rdi,%rdx\) +** movups %xmm0, -32\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movzwl \(%rsi\), %edi +** movzwl -2\(%rsi,%rdx\), %ecx +** movw %di, \(%rax\) +** movw %cx, -2\(%rax,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +#ifndef gcc_memmove +#define gcc_memmove gcc_memmove_xmm +#endif + +void * +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + return __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-2b.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-2b.c new file mode 100644 index 0000000..0596ca7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-2b.c @@ -0,0 +1,173 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx512f -march=x86-64-v3 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_ymm: +**.LFB0: +** .cfi_startproc +** movq %rdi, %rax +** movq %rsi, %rcx +** cmpq \$32, %rdx +** jb .L3 +** cmpq \$64, %rdx +** jbe .L18 +** cmpq \$256, %rdx +** jbe .L19 +** movq %rdx, %rsi +** cmpq %rdi, %rcx +** jb .L12 +** je .L2 +** vmovdqu -32\(%rcx,%rdx\), %ymm7 +** vmovdqu -64\(%rcx,%rdx\), %ymm6 +** vmovdqu -96\(%rcx,%rdx\), %ymm5 +** vmovdqu -128\(%rcx,%rdx\), %ymm4 +**.L13: +** vmovdqu \(%rcx\), %ymm3 +** addq \$-128, %rsi +** subq \$-128, %rdi +** subq \$-128, %rcx +** vmovdqu -96\(%rcx\), %ymm2 +** vmovdqu -64\(%rcx\), %ymm1 +** vmovdqu -32\(%rcx\), %ymm0 +** vmovdqu %ymm3, -128\(%rdi\) +** vmovdqu %ymm2, -96\(%rdi\) +** vmovdqu %ymm1, -64\(%rdi\) +** vmovdqu %ymm0, -32\(%rdi\) +** cmpq \$128, %rsi +** ja .L13 +** vmovdqu %ymm7, -32\(%rax,%rdx\) +** vmovdqu %ymm6, -64\(%rax,%rdx\) +** vmovdqu %ymm5, -96\(%rax,%rdx\) +** vmovdqu %ymm4, -128\(%rax,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L3: +** cmpq \$16, %rdx +** jb .L20 +** vmovdqu \(%rsi\), %xmm1 +** vmovdqu -16\(%rsi,%rdx\), %xmm0 +** vmovdqu %xmm1, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L20: +** cmpq \$8, %rdx +** jnb .L6 +** cmpq \$4, %rdx +** jnb .L7 +** cmpq \$1, %rdx +** ja .L8 +** jb .L2 +** movzbl \(%rsi\), %edx +** movb %dl, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L18: +** vmovdqu \(%rsi\), %ymm1 +** vmovdqu -32\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm1, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** cmpq \$128, %rdx +** jb .L11 +** vmovdqu \(%rsi\), %ymm7 +** vmovdqu 32\(%rsi\), %ymm6 +** vmovdqu 64\(%rsi\), %ymm5 +** vmovdqu 96\(%rsi\), %ymm4 +** vmovdqu -32\(%rsi,%rdx\), %ymm3 +** vmovdqu -64\(%rsi,%rdx\), %ymm2 +** vmovdqu -96\(%rsi,%rdx\), %ymm1 +** vmovdqu -128\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm7, \(%rdi\) +** vmovdqu %ymm6, 32\(%rdi\) +** vmovdqu %ymm5, 64\(%rdi\) +** vmovdqu %ymm4, 96\(%rdi\) +** vmovdqu %ymm3, -32\(%rdi,%rdx\) +** vmovdqu %ymm2, -64\(%rdi,%rdx\) +** vmovdqu %ymm1, -96\(%rdi,%rdx\) +** vmovdqu %ymm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movq \(%rsi\), %rdi +** movq -8\(%rsi,%rdx\), %rcx +** movq %rdi, \(%rax\) +** movq %rcx, -8\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L12: +** vmovdqu \(%rcx\), %ymm7 +** vmovdqu 32\(%rcx\), %ymm6 +** leaq \(%rdi,%rdx\), %rdi +** vmovdqu 64\(%rcx\), %ymm5 +** vmovdqu 96\(%rcx\), %ymm4 +** addq %rdx, %rcx +**.L14: +** vmovdqu -32\(%rcx\), %ymm3 +** vmovdqu -64\(%rcx\), %ymm2 +** addq \$-128, %rsi +** addq \$-128, %rdi +** vmovdqu -96\(%rcx\), %ymm1 +** vmovdqu -128\(%rcx\), %ymm0 +** addq \$-128, %rcx +** vmovdqu %ymm3, 96\(%rdi\) +** vmovdqu %ymm2, 64\(%rdi\) +** vmovdqu %ymm1, 32\(%rdi\) +** vmovdqu %ymm0, \(%rdi\) +** cmpq \$128, %rsi +** ja .L14 +** vmovdqu %ymm7, \(%rax\) +** vmovdqu %ymm6, 32\(%rax\) +** vmovdqu %ymm5, 64\(%rax\) +** vmovdqu %ymm4, 96\(%rax\) +** vzeroupper +**.L2: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L11: +** vmovdqu \(%rsi\), %ymm3 +** vmovdqu 32\(%rsi\), %ymm2 +** vmovdqu -32\(%rsi,%rdx\), %ymm1 +** vmovdqu -64\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm3, \(%rdi\) +** vmovdqu %ymm2, 32\(%rdi\) +** vmovdqu %ymm1, -32\(%rdi,%rdx\) +** vmovdqu %ymm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movl \(%rsi\), %edi +** movl -4\(%rsi,%rdx\), %ecx +** movl %edi, \(%rax\) +** movl %ecx, -4\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** movzwl \(%rsi\), %edi +** movzwl -2\(%rsi,%rdx\), %ecx +** movw %di, \(%rax\) +** movw %cx, -2\(%rax,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_ymm +#include "builtin-memmove-2a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-2c.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-2c.c new file mode 100644 index 0000000..cb3cb9e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-2c.c @@ -0,0 +1,184 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -mmove-max=512 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_zmm: +**.LFB0: +** .cfi_startproc +** movq %rdi, %rax +** movq %rsi, %rcx +** cmpq \$64, %rdx +** jb .L3 +** cmpq \$128, %rdx +** jbe .L19 +** cmpq \$512, %rdx +** jbe .L20 +** movq %rdx, %rsi +** cmpq %rdi, %rcx +** jb .L13 +** je .L2 +** vmovdqu64 -64\(%rcx,%rdx\), %zmm7 +** vmovdqu64 -128\(%rcx,%rdx\), %zmm6 +** vmovdqu64 -192\(%rcx,%rdx\), %zmm5 +** vmovdqu64 -256\(%rcx,%rdx\), %zmm4 +**.L14: +** vmovdqu64 \(%rcx\), %zmm3 +** vmovdqu64 64\(%rcx\), %zmm2 +** subq \$256, %rsi +** addq \$256, %rdi +** vmovdqu64 128\(%rcx\), %zmm1 +** addq \$256, %rcx +** vmovdqu64 -64\(%rcx\), %zmm0 +** vmovdqu64 %zmm3, -256\(%rdi\) +** vmovdqu64 %zmm2, -192\(%rdi\) +** vmovdqu64 %zmm1, -128\(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi\) +** cmpq \$256, %rsi +** ja .L14 +** vmovdqu64 %zmm7, -64\(%rax,%rdx\) +** vmovdqu64 %zmm6, -128\(%rax,%rdx\) +** vmovdqu64 %zmm5, -192\(%rax,%rdx\) +** vmovdqu64 %zmm4, -256\(%rax,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L3: +** cmpq \$32, %rdx +** jb .L21 +** vmovdqu \(%rsi\), %ymm1 +** vmovdqu -32\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm1, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L21: +** cmpq \$16, %rdx +** jnb .L6 +** cmpq \$8, %rdx +** jnb .L7 +** cmpq \$4, %rdx +** jnb .L8 +** cmpq \$1, %rdx +** ja .L9 +** jb .L2 +** movzbl \(%rsi\), %edx +** movb %dl, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** vmovdqu64 \(%rsi\), %zmm1 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm1, \(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L20: +** cmpq \$256, %rdx +** jb .L12 +** vmovdqu64 \(%rsi\), %zmm7 +** vmovdqu64 64\(%rsi\), %zmm6 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm3 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm2 +** vmovdqu64 128\(%rsi\), %zmm5 +** vmovdqu64 192\(%rsi\), %zmm4 +** vmovdqu64 -192\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -256\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm7, \(%rdi\) +** vmovdqu64 %zmm6, 64\(%rdi\) +** vmovdqu64 %zmm5, 128\(%rdi\) +** vmovdqu64 %zmm4, 192\(%rdi\) +** vmovdqu64 %zmm3, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm2, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm1, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -256\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** vmovdqu \(%rsi\), %xmm1 +** vmovdqu -16\(%rsi,%rdx\), %xmm0 +** vmovdqu %xmm1, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** vmovdqu64 \(%rcx\), %zmm7 +** leaq \(%rdi,%rdx\), %rdi +** vmovdqu64 64\(%rcx\), %zmm6 +** vmovdqu64 128\(%rcx\), %zmm5 +** vmovdqu64 192\(%rcx\), %zmm4 +** addq %rdx, %rcx +**.L15: +** vmovdqu64 -64\(%rcx\), %zmm3 +** vmovdqu64 -128\(%rcx\), %zmm2 +** subq \$256, %rsi +** subq \$256, %rdi +** vmovdqu64 -192\(%rcx\), %zmm1 +** subq \$256, %rcx +** vmovdqu64 \(%rcx\), %zmm0 +** vmovdqu64 %zmm3, 192\(%rdi\) +** vmovdqu64 %zmm2, 128\(%rdi\) +** vmovdqu64 %zmm1, 64\(%rdi\) +** vmovdqu64 %zmm0, \(%rdi\) +** cmpq \$256, %rsi +** ja .L15 +** vmovdqu64 %zmm7, \(%rax\) +** vmovdqu64 %zmm6, 64\(%rax\) +** vmovdqu64 %zmm5, 128\(%rax\) +** vmovdqu64 %zmm4, 192\(%rax\) +** vzeroupper +**.L2: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L12: +** vmovdqu64 \(%rsi\), %zmm3 +** vmovdqu64 64\(%rsi\), %zmm2 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm3, \(%rdi\) +** vmovdqu64 %zmm2, 64\(%rdi\) +** vmovdqu64 %zmm1, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movq \(%rsi\), %rdi +** movq -8\(%rsi,%rdx\), %rcx +** movq %rdi, \(%rax\) +** movq %rcx, -8\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** movl \(%rsi\), %edi +** movl -4\(%rsi,%rdx\), %ecx +** movl %edi, \(%rax\) +** movl %ecx, -4\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L9: +** movzwl \(%rsi\), %edi +** movzwl -2\(%rsi,%rdx\), %ecx +** movw %di, \(%rax\) +** movw %cx, -2\(%rax,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_zmm +#include "builtin-memmove-2a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-2d.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-2d.c new file mode 100644 index 0000000..c27edfe --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-2d.c @@ -0,0 +1,195 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mgeneral-regs-only -march=x86-64 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_gpr: +**.LFB0: +** .cfi_startproc +** movq %rdi, %rax +** cmpq \$8, %rdx +** jb .L3 +** cmpq \$16, %rdx +** jbe .L19 +** subq \$32, %rsp +** .cfi_def_cfa_offset 40 +** cmpq \$64, %rdx +** jbe .L20 +** movq %rsi, %rcx +** movq %rdx, %rsi +** cmpq %rdi, %rcx +** jb .L10 +** je .L2 +** movq %rbx, \(%rsp\) +** movq %rbp, 8\(%rsp\) +** movq %r14, 16\(%rsp\) +** movq %r15, 24\(%rsp\) +** .cfi_offset 3, -40 +** .cfi_offset 6, -32 +** .cfi_offset 14, -24 +** .cfi_offset 15, -16 +** movq -8\(%rcx,%rdx\), %r15 +** movq -16\(%rcx,%rdx\), %r14 +** movq -24\(%rcx,%rdx\), %rbp +** movq -32\(%rcx,%rdx\), %r11 +**.L11: +** movq 8\(%rcx\), %r10 +** movq 16\(%rcx\), %r9 +** subq \$32, %rsi +** addq \$32, %rdi +** movq 24\(%rcx\), %r8 +** movq \(%rcx\), %rbx +** addq \$32, %rcx +** movq %r10, -24\(%rdi\) +** movq %rbx, -32\(%rdi\) +** movq %r9, -16\(%rdi\) +** movq %r8, -8\(%rdi\) +** cmpq \$32, %rsi +** ja .L11 +** movq %r15, -8\(%rax,%rdx\) +** movq %r14, -16\(%rax,%rdx\) +** movq %rbp, -24\(%rax,%rdx\) +** movq %r11, -32\(%rax,%rdx\) +** movq \(%rsp\), %rbx +** .cfi_restore 3 +** movq 8\(%rsp\), %rbp +** .cfi_restore 6 +** movq 16\(%rsp\), %r14 +** .cfi_restore 14 +** movq 24\(%rsp\), %r15 +** .cfi_restore 15 +** jmp .L2 +** .p2align 4,,10 +** .p2align 3 +**.L3: +** .cfi_def_cfa_offset 8 +** cmpq \$4, %rdx +** jb .L21 +** movl \(%rsi\), %edi +** movl -4\(%rsi,%rdx\), %ecx +** movl %edi, \(%rax\) +** movl %ecx, -4\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L21: +** cmpq \$1, %rdx +** ja .L6 +** jb .L16 +** movzbl \(%rsi\), %edx +** movb %dl, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** movq \(%rsi\), %rdi +** movq -8\(%rsi,%rdx\), %rcx +** movq %rdi, \(%rax\) +** movq %rcx, -8\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L20: +** .cfi_def_cfa_offset 40 +** cmpq \$32, %rdx +** jb .L9 +** movq %rbx, \(%rsp\) +** movq %r14, 16\(%rsp\) +** .cfi_offset 3, -40 +** .cfi_offset 14, -24 +** movq \(%rsi\), %rbx +** movq 8\(%rsi\), %r14 +** movq 16\(%rsi\), %r11 +** movq 24\(%rsi\), %r10 +** movq -8\(%rsi,%rdx\), %r9 +** movq -16\(%rsi,%rdx\), %r8 +** movq -24\(%rsi,%rdx\), %rdi +** movq -32\(%rsi,%rdx\), %rcx +** movq %rbx, \(%rax\) +** movq %r14, 8\(%rax\) +** movq %r11, 16\(%rax\) +** movq %r10, 24\(%rax\) +** movq %r9, -8\(%rax,%rdx\) +** movq %r8, -16\(%rax,%rdx\) +** movq %rdi, -24\(%rax,%rdx\) +** movq %rcx, -32\(%rax,%rdx\) +** movq \(%rsp\), %rbx +** .cfi_restore 3 +** movq 16\(%rsp\), %r14 +** .cfi_restore 14 +**.L2: +** addq \$32, %rsp +** .cfi_def_cfa_offset 8 +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movzwl \(%rsi\), %edi +** movzwl -2\(%rsi,%rdx\), %ecx +** movw %di, \(%rax\) +** movw %cx, -2\(%rax,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L16: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L9: +** .cfi_def_cfa_offset 40 +** movq \(%rsi\), %r9 +** movq 8\(%rsi\), %r8 +** movq -8\(%rsi,%rdx\), %rdi +** movq -16\(%rsi,%rdx\), %rcx +** movq %r9, \(%rax\) +** movq %r8, 8\(%rax\) +** movq %rdi, -8\(%rax,%rdx\) +** movq %rcx, -16\(%rax,%rdx\) +** jmp .L2 +** .p2align 4,,10 +** .p2align 3 +**.L10: +** movq %rbx, \(%rsp\) +** leaq \(%rdi,%rdx\), %rdi +** movq %r14, 16\(%rsp\) +** movq %r15, 24\(%rsp\) +** .cfi_offset 3, -40 +** .cfi_offset 14, -24 +** .cfi_offset 15, -16 +** movq \(%rcx\), %r14 +** movq 8\(%rcx\), %r15 +** movq 16\(%rcx\), %r10 +** movq 24\(%rcx\), %r11 +** addq %rdx, %rcx +**.L12: +** movq -16\(%rcx\), %r9 +** movq -24\(%rcx\), %r8 +** subq \$32, %rsi +** subq \$32, %rdi +** movq -32\(%rcx\), %rdx +** movq -8\(%rcx\), %rbx +** subq \$32, %rcx +** movq %r9, 16\(%rdi\) +** movq %rbx, 24\(%rdi\) +** movq %r8, 8\(%rdi\) +** movq %rdx, \(%rdi\) +** cmpq \$32, %rsi +** ja .L12 +** movq %r14, \(%rax\) +** movq \(%rsp\), %rbx +** .cfi_restore 3 +** movq %r15, 8\(%rax\) +** movq 16\(%rsp\), %r14 +** .cfi_restore 14 +** movq %r10, 16\(%rax\) +** movq 24\(%rsp\), %r15 +** .cfi_restore 15 +** movq %r11, 24\(%rax\) +** jmp .L2 +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_gpr +#include "builtin-memmove-2a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-3a.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-3a.c new file mode 100644 index 0000000..83cb8e1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-3a.c @@ -0,0 +1,133 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_xmm: +**.LFB0: +** .cfi_startproc +** cmpq \$16, %rdx +** ja .L13 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$32, %rdx +** jbe .L14 +** cmpq \$128, %rdx +** ja .L5 +** cmpq \$64, %rdx +** jnb .L15 +** movdqu \(%rsi\), %xmm3 +** movdqu 16\(%rsi\), %xmm2 +** movdqu -16\(%rsi,%rdx\), %xmm1 +** movdqu -32\(%rsi,%rdx\), %xmm0 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, -16\(%rdi,%rdx\) +** movups %xmm0, -32\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L14: +** movdqu \(%rsi\), %xmm1 +** movdqu -16\(%rsi,%rdx\), %xmm0 +** movups %xmm1, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L7 +** je .L1 +** movdqu -16\(%rax,%rdx\), %xmm7 +** movdqu -32\(%rax,%rdx\), %xmm6 +** movdqu -48\(%rax,%rdx\), %xmm5 +** movdqu -64\(%rax,%rdx\), %xmm4 +**.L8: +** movdqu \(%rax\), %xmm3 +** subq \$64, %rsi +** addq \$64, %rcx +** addq \$64, %rax +** movdqu -48\(%rax\), %xmm2 +** movdqu -32\(%rax\), %xmm1 +** movdqu -16\(%rax\), %xmm0 +** movups %xmm3, -64\(%rcx\) +** movups %xmm2, -48\(%rcx\) +** movups %xmm1, -32\(%rcx\) +** movups %xmm0, -16\(%rcx\) +** cmpq \$64, %rsi +** ja .L8 +** movups %xmm7, -16\(%rdi,%rdx\) +** movups %xmm6, -32\(%rdi,%rdx\) +** movups %xmm5, -48\(%rdi,%rdx\) +** movups %xmm4, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movdqu \(%rax\), %xmm3 +** movdqu 16\(%rax\), %xmm2 +** leaq \(%rdi,%rdx\), %rcx +** movdqu 32\(%rax\), %xmm1 +** movdqu 48\(%rax\), %xmm0 +** addq %rdx, %rax +**.L9: +** movdqu -16\(%rax\), %xmm7 +** movdqu -32\(%rax\), %xmm6 +** subq \$64, %rsi +** subq \$64, %rcx +** movdqu -48\(%rax\), %xmm5 +** movdqu -64\(%rax\), %xmm4 +** subq \$64, %rax +** movups %xmm7, 48\(%rcx\) +** movups %xmm6, 32\(%rcx\) +** movups %xmm5, 16\(%rcx\) +** movups %xmm4, \(%rcx\) +** cmpq \$64, %rsi +** ja .L9 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, 32\(%rdi\) +** movups %xmm0, 48\(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L15: +** movdqu \(%rsi\), %xmm7 +** movdqu 16\(%rsi\), %xmm6 +** movdqu 32\(%rsi\), %xmm5 +** movdqu 48\(%rsi\), %xmm4 +** movdqu -16\(%rsi,%rdx\), %xmm3 +** movdqu -32\(%rsi,%rdx\), %xmm2 +** movdqu -48\(%rsi,%rdx\), %xmm1 +** movdqu -64\(%rsi,%rdx\), %xmm0 +** movups %xmm7, \(%rdi\) +** movups %xmm6, 16\(%rdi\) +** movups %xmm5, 32\(%rdi\) +** movups %xmm4, 48\(%rdi\) +** movups %xmm3, -16\(%rdi,%rdx\) +** movups %xmm2, -32\(%rdi,%rdx\) +** movups %xmm1, -48\(%rdi,%rdx\) +** movups %xmm0, -64\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +#ifndef gcc_memmove +#define gcc_memmove gcc_memmove_xmm +#endif + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n > 16) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-3b.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-3b.c new file mode 100644 index 0000000..43fae5c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-3b.c @@ -0,0 +1,140 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx512f -march=x86-64-v3 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_ymm: +**.LFB0: +** .cfi_startproc +** cmpq \$16, %rdx +** ja .L16 +**.L14: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L16: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$32, %rdx +** jb .L6 +** cmpq \$64, %rdx +** ja .L5 +** vmovdqu \(%rsi\), %ymm1 +** vmovdqu -32\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm1, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** vmovdqu \(%rsi\), %xmm1 +** vmovdqu -16\(%rsi,%rdx\), %xmm0 +** vmovdqu %xmm1, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** cmpq \$256, %rdx +** jbe .L17 +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L9 +** je .L14 +** vmovdqu -32\(%rax,%rdx\), %ymm7 +** vmovdqu -64\(%rax,%rdx\), %ymm6 +** vmovdqu -96\(%rax,%rdx\), %ymm5 +** vmovdqu -128\(%rax,%rdx\), %ymm4 +**.L10: +** vmovdqu \(%rax\), %ymm3 +** addq \$-128, %rsi +** subq \$-128, %rcx +** subq \$-128, %rax +** vmovdqu -96\(%rax\), %ymm2 +** vmovdqu -64\(%rax\), %ymm1 +** vmovdqu -32\(%rax\), %ymm0 +** vmovdqu %ymm3, -128\(%rcx\) +** vmovdqu %ymm2, -96\(%rcx\) +** vmovdqu %ymm1, -64\(%rcx\) +** vmovdqu %ymm0, -32\(%rcx\) +** cmpq \$128, %rsi +** ja .L10 +** vmovdqu %ymm7, -32\(%rdi,%rdx\) +** vmovdqu %ymm6, -64\(%rdi,%rdx\) +** vmovdqu %ymm5, -96\(%rdi,%rdx\) +** vmovdqu %ymm4, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L17: +** cmpq \$128, %rdx +** jb .L8 +** vmovdqu \(%rsi\), %ymm7 +** vmovdqu 32\(%rsi\), %ymm6 +** vmovdqu 64\(%rsi\), %ymm5 +** vmovdqu 96\(%rsi\), %ymm4 +** vmovdqu -32\(%rsi,%rdx\), %ymm3 +** vmovdqu -64\(%rsi,%rdx\), %ymm2 +** vmovdqu -96\(%rsi,%rdx\), %ymm1 +** vmovdqu -128\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm7, \(%rdi\) +** vmovdqu %ymm6, 32\(%rdi\) +** vmovdqu %ymm5, 64\(%rdi\) +** vmovdqu %ymm4, 96\(%rdi\) +** vmovdqu %ymm3, -32\(%rdi,%rdx\) +** vmovdqu %ymm2, -64\(%rdi,%rdx\) +** vmovdqu %ymm1, -96\(%rdi,%rdx\) +** vmovdqu %ymm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** vmovdqu \(%rsi\), %ymm3 +** vmovdqu 32\(%rsi\), %ymm2 +** vmovdqu -32\(%rsi,%rdx\), %ymm1 +** vmovdqu -64\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm3, \(%rdi\) +** vmovdqu %ymm2, 32\(%rdi\) +** vmovdqu %ymm1, -32\(%rdi,%rdx\) +** vmovdqu %ymm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L9: +** vmovdqu \(%rax\), %ymm3 +** vmovdqu 32\(%rax\), %ymm2 +** leaq \(%rdi,%rdx\), %rcx +** vmovdqu 64\(%rax\), %ymm1 +** vmovdqu 96\(%rax\), %ymm0 +** addq %rdx, %rax +**.L11: +** vmovdqu -32\(%rax\), %ymm7 +** vmovdqu -64\(%rax\), %ymm6 +** addq \$-128, %rsi +** addq \$-128, %rcx +** vmovdqu -96\(%rax\), %ymm5 +** vmovdqu -128\(%rax\), %ymm4 +** addq \$-128, %rax +** vmovdqu %ymm7, 96\(%rcx\) +** vmovdqu %ymm6, 64\(%rcx\) +** vmovdqu %ymm5, 32\(%rcx\) +** vmovdqu %ymm4, \(%rcx\) +** cmpq \$128, %rsi +** ja .L11 +** vmovdqu %ymm3, \(%rdi\) +** vmovdqu %ymm2, 32\(%rdi\) +** vmovdqu %ymm1, 64\(%rdi\) +** vmovdqu %ymm0, 96\(%rdi\) +** vzeroupper +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_ymm +#include "builtin-memmove-3a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-3c.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-3c.c new file mode 100644 index 0000000..11ccb69 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-3c.c @@ -0,0 +1,151 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -mmove-max=512 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_zmm: +**.LFB0: +** .cfi_startproc +** cmpq \$16, %rdx +** ja .L18 +**.L16: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L18: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$64, %rdx +** jnb .L19 +** cmpq \$32, %rdx +** jb .L15 +** vmovdqu \(%rsi\), %ymm1 +** vmovdqu -32\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm1, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** cmpq \$128, %rdx +** ja .L5 +** vmovdqu64 \(%rsi\), %zmm1 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm1, \(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** cmpq \$512, %rdx +** jbe .L20 +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L10 +** je .L16 +** vmovdqu64 -64\(%rax,%rdx\), %zmm7 +** vmovdqu64 -128\(%rax,%rdx\), %zmm6 +** vmovdqu64 -192\(%rax,%rdx\), %zmm5 +** vmovdqu64 -256\(%rax,%rdx\), %zmm4 +**.L11: +** vmovdqu64 \(%rax\), %zmm3 +** addq \$256, %rax +** vmovdqu64 -192\(%rax\), %zmm2 +** subq \$256, %rsi +** vmovdqu64 -128\(%rax\), %zmm1 +** vmovdqu64 -64\(%rax\), %zmm0 +** addq \$256, %rcx +** vmovdqu64 %zmm3, -256\(%rcx\) +** vmovdqu64 %zmm2, -192\(%rcx\) +** vmovdqu64 %zmm1, -128\(%rcx\) +** vmovdqu64 %zmm0, -64\(%rcx\) +** cmpq \$256, %rsi +** ja .L11 +** vmovdqu64 %zmm7, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm6, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm5, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm4, -256\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L15: +** vmovdqu \(%rsi\), %xmm1 +** vmovdqu -16\(%rsi,%rdx\), %xmm0 +** vmovdqu %xmm1, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L20: +** cmpq \$256, %rdx +** jb .L9 +** vmovdqu64 \(%rsi\), %zmm7 +** vmovdqu64 64\(%rsi\), %zmm6 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm3 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm2 +** vmovdqu64 128\(%rsi\), %zmm5 +** vmovdqu64 192\(%rsi\), %zmm4 +** vmovdqu64 -192\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -256\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm7, \(%rdi\) +** vmovdqu64 %zmm6, 64\(%rdi\) +** vmovdqu64 %zmm5, 128\(%rdi\) +** vmovdqu64 %zmm4, 192\(%rdi\) +** vmovdqu64 %zmm3, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm2, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm1, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -256\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L9: +** vmovdqu64 \(%rsi\), %zmm3 +** vmovdqu64 64\(%rsi\), %zmm2 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm3, \(%rdi\) +** vmovdqu64 %zmm2, 64\(%rdi\) +** vmovdqu64 %zmm1, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L10: +** vmovdqu64 \(%rax\), %zmm3 +** leaq \(%rdi,%rdx\), %rcx +** vmovdqu64 64\(%rax\), %zmm2 +** vmovdqu64 128\(%rax\), %zmm1 +** vmovdqu64 192\(%rax\), %zmm0 +** addq %rdx, %rax +**.L12: +** vmovdqu64 -64\(%rax\), %zmm7 +** subq \$256, %rax +** vmovdqu64 128\(%rax\), %zmm6 +** subq \$256, %rsi +** vmovdqu64 64\(%rax\), %zmm5 +** vmovdqu64 \(%rax\), %zmm4 +** subq \$256, %rcx +** vmovdqu64 %zmm7, 192\(%rcx\) +** vmovdqu64 %zmm6, 128\(%rcx\) +** vmovdqu64 %zmm5, 64\(%rcx\) +** vmovdqu64 %zmm4, \(%rcx\) +** cmpq \$256, %rsi +** ja .L12 +** vmovdqu64 %zmm3, \(%rdi\) +** vmovdqu64 %zmm2, 64\(%rdi\) +** vmovdqu64 %zmm1, 128\(%rdi\) +** vmovdqu64 %zmm0, 192\(%rdi\) +** vzeroupper +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_zmm +#include "builtin-memmove-3a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-4a.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-4a.c new file mode 100644 index 0000000..c437a53 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-4a.c @@ -0,0 +1,123 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_xmm: +**.LFB0: +** .cfi_startproc +** cmpq \$32, %rdx +** ja .L13 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$128, %rdx +** jbe .L14 +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L7 +** je .L1 +** movdqu -16\(%rax,%rdx\), %xmm7 +** movdqu -32\(%rax,%rdx\), %xmm6 +** movdqu -48\(%rax,%rdx\), %xmm5 +** movdqu -64\(%rax,%rdx\), %xmm4 +**.L8: +** movdqu \(%rax\), %xmm3 +** subq \$64, %rsi +** addq \$64, %rcx +** addq \$64, %rax +** movdqu -48\(%rax\), %xmm2 +** movdqu -32\(%rax\), %xmm1 +** movdqu -16\(%rax\), %xmm0 +** movups %xmm3, -64\(%rcx\) +** movups %xmm2, -48\(%rcx\) +** movups %xmm1, -32\(%rcx\) +** movups %xmm0, -16\(%rcx\) +** cmpq \$64, %rsi +** ja .L8 +** movups %xmm7, -16\(%rdi,%rdx\) +** movups %xmm6, -32\(%rdi,%rdx\) +** movups %xmm5, -48\(%rdi,%rdx\) +** movups %xmm4, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L14: +** cmpq \$64, %rdx +** jb .L6 +** movdqu \(%rsi\), %xmm7 +** movdqu 16\(%rsi\), %xmm6 +** movdqu 32\(%rsi\), %xmm5 +** movdqu 48\(%rsi\), %xmm4 +** movdqu -16\(%rsi,%rdx\), %xmm3 +** movdqu -32\(%rsi,%rdx\), %xmm2 +** movdqu -48\(%rsi,%rdx\), %xmm1 +** movdqu -64\(%rsi,%rdx\), %xmm0 +** movups %xmm7, \(%rdi\) +** movups %xmm6, 16\(%rdi\) +** movups %xmm5, 32\(%rdi\) +** movups %xmm4, 48\(%rdi\) +** movups %xmm3, -16\(%rdi,%rdx\) +** movups %xmm2, -32\(%rdi,%rdx\) +** movups %xmm1, -48\(%rdi,%rdx\) +** movups %xmm0, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movdqu \(%rsi\), %xmm3 +** movdqu 16\(%rsi\), %xmm2 +** movdqu -16\(%rsi,%rdx\), %xmm1 +** movdqu -32\(%rsi,%rdx\), %xmm0 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, -16\(%rdi,%rdx\) +** movups %xmm0, -32\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movdqu \(%rax\), %xmm3 +** movdqu 16\(%rax\), %xmm2 +** leaq \(%rdi,%rdx\), %rcx +** movdqu 32\(%rax\), %xmm1 +** movdqu 48\(%rax\), %xmm0 +** addq %rdx, %rax +**.L9: +** movdqu -16\(%rax\), %xmm7 +** movdqu -32\(%rax\), %xmm6 +** subq \$64, %rsi +** subq \$64, %rcx +** movdqu -48\(%rax\), %xmm5 +** movdqu -64\(%rax\), %xmm4 +** subq \$64, %rax +** movups %xmm7, 48\(%rcx\) +** movups %xmm6, 32\(%rcx\) +** movups %xmm5, 16\(%rcx\) +** movups %xmm4, \(%rcx\) +** cmpq \$64, %rsi +** ja .L9 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, 32\(%rdi\) +** movups %xmm0, 48\(%rdi\) +** ret +** .cfi_endproc +**... +*/ + +#ifndef gcc_memmove +#define gcc_memmove gcc_memmove_xmm +#endif + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n > 32) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-4b.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-4b.c new file mode 100644 index 0000000..4b65fca --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-4b.c @@ -0,0 +1,130 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx512f -march=x86-64-v3 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_ymm: +**.LFB0: +** .cfi_startproc +** cmpq \$32, %rdx +** ja .L14 +**.L12: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L14: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$64, %rdx +** jbe .L15 +** cmpq \$256, %rdx +** ja .L5 +** cmpq \$128, %rdx +** jnb .L16 +** vmovdqu \(%rsi\), %ymm3 +** vmovdqu 32\(%rsi\), %ymm2 +** vmovdqu -32\(%rsi,%rdx\), %ymm1 +** vmovdqu -64\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm3, \(%rdi\) +** vmovdqu %ymm2, 32\(%rdi\) +** vmovdqu %ymm1, -32\(%rdi,%rdx\) +** vmovdqu %ymm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L15: +** vmovdqu \(%rsi\), %ymm1 +** vmovdqu -32\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm1, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L7 +** je .L12 +** vmovdqu -32\(%rax,%rdx\), %ymm7 +** vmovdqu -64\(%rax,%rdx\), %ymm6 +** vmovdqu -96\(%rax,%rdx\), %ymm5 +** vmovdqu -128\(%rax,%rdx\), %ymm4 +**.L8: +** vmovdqu \(%rax\), %ymm3 +** addq \$-128, %rsi +** subq \$-128, %rcx +** subq \$-128, %rax +** vmovdqu -96\(%rax\), %ymm2 +** vmovdqu -64\(%rax\), %ymm1 +** vmovdqu -32\(%rax\), %ymm0 +** vmovdqu %ymm3, -128\(%rcx\) +** vmovdqu %ymm2, -96\(%rcx\) +** vmovdqu %ymm1, -64\(%rcx\) +** vmovdqu %ymm0, -32\(%rcx\) +** cmpq \$128, %rsi +** ja .L8 +** vmovdqu %ymm7, -32\(%rdi,%rdx\) +** vmovdqu %ymm6, -64\(%rdi,%rdx\) +** vmovdqu %ymm5, -96\(%rdi,%rdx\) +** vmovdqu %ymm4, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** vmovdqu \(%rax\), %ymm3 +** vmovdqu 32\(%rax\), %ymm2 +** leaq \(%rdi,%rdx\), %rcx +** vmovdqu 64\(%rax\), %ymm1 +** vmovdqu 96\(%rax\), %ymm0 +** addq %rdx, %rax +**.L9: +** vmovdqu -32\(%rax\), %ymm7 +** vmovdqu -64\(%rax\), %ymm6 +** addq \$-128, %rsi +** addq \$-128, %rcx +** vmovdqu -96\(%rax\), %ymm5 +** vmovdqu -128\(%rax\), %ymm4 +** addq \$-128, %rax +** vmovdqu %ymm7, 96\(%rcx\) +** vmovdqu %ymm6, 64\(%rcx\) +** vmovdqu %ymm5, 32\(%rcx\) +** vmovdqu %ymm4, \(%rcx\) +** cmpq \$128, %rsi +** ja .L9 +** vmovdqu %ymm3, \(%rdi\) +** vmovdqu %ymm2, 32\(%rdi\) +** vmovdqu %ymm1, 64\(%rdi\) +** vmovdqu %ymm0, 96\(%rdi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L16: +** vmovdqu \(%rsi\), %ymm7 +** vmovdqu 32\(%rsi\), %ymm6 +** vmovdqu 64\(%rsi\), %ymm5 +** vmovdqu 96\(%rsi\), %ymm4 +** vmovdqu -32\(%rsi,%rdx\), %ymm3 +** vmovdqu -64\(%rsi,%rdx\), %ymm2 +** vmovdqu -96\(%rsi,%rdx\), %ymm1 +** vmovdqu -128\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm7, \(%rdi\) +** vmovdqu %ymm6, 32\(%rdi\) +** vmovdqu %ymm5, 64\(%rdi\) +** vmovdqu %ymm4, 96\(%rdi\) +** vmovdqu %ymm3, -32\(%rdi,%rdx\) +** vmovdqu %ymm2, -64\(%rdi,%rdx\) +** vmovdqu %ymm1, -96\(%rdi,%rdx\) +** vmovdqu %ymm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_ymm +#include "builtin-memmove-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-4c.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-4c.c new file mode 100644 index 0000000..fea3e49 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-4c.c @@ -0,0 +1,141 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -mmove-max=512 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_zmm: +**.LFB0: +** .cfi_startproc +** cmpq \$32, %rdx +** ja .L16 +**.L14: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L16: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$64, %rdx +** jb .L6 +** cmpq \$128, %rdx +** ja .L5 +** vmovdqu64 \(%rsi\), %zmm1 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm1, \(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** vmovdqu \(%rsi\), %ymm1 +** vmovdqu -32\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm1, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** cmpq \$512, %rdx +** jbe .L17 +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L9 +** je .L14 +** vmovdqu64 -64\(%rax,%rdx\), %zmm7 +** vmovdqu64 -128\(%rax,%rdx\), %zmm6 +** vmovdqu64 -192\(%rax,%rdx\), %zmm5 +** vmovdqu64 -256\(%rax,%rdx\), %zmm4 +**.L10: +** vmovdqu64 \(%rax\), %zmm3 +** addq \$256, %rax +** vmovdqu64 -192\(%rax\), %zmm2 +** subq \$256, %rsi +** vmovdqu64 -128\(%rax\), %zmm1 +** vmovdqu64 -64\(%rax\), %zmm0 +** addq \$256, %rcx +** vmovdqu64 %zmm3, -256\(%rcx\) +** vmovdqu64 %zmm2, -192\(%rcx\) +** vmovdqu64 %zmm1, -128\(%rcx\) +** vmovdqu64 %zmm0, -64\(%rcx\) +** cmpq \$256, %rsi +** ja .L10 +** vmovdqu64 %zmm7, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm6, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm5, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm4, -256\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L17: +** cmpq \$256, %rdx +** jb .L8 +** vmovdqu64 \(%rsi\), %zmm7 +** vmovdqu64 64\(%rsi\), %zmm6 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm3 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm2 +** vmovdqu64 128\(%rsi\), %zmm5 +** vmovdqu64 192\(%rsi\), %zmm4 +** vmovdqu64 -192\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -256\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm7, \(%rdi\) +** vmovdqu64 %zmm6, 64\(%rdi\) +** vmovdqu64 %zmm5, 128\(%rdi\) +** vmovdqu64 %zmm4, 192\(%rdi\) +** vmovdqu64 %zmm3, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm2, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm1, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -256\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** vmovdqu64 \(%rsi\), %zmm3 +** vmovdqu64 64\(%rsi\), %zmm2 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm3, \(%rdi\) +** vmovdqu64 %zmm2, 64\(%rdi\) +** vmovdqu64 %zmm1, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L9: +** vmovdqu64 \(%rax\), %zmm3 +** leaq \(%rdi,%rdx\), %rcx +** vmovdqu64 64\(%rax\), %zmm2 +** vmovdqu64 128\(%rax\), %zmm1 +** vmovdqu64 192\(%rax\), %zmm0 +** addq %rdx, %rax +**.L11: +** vmovdqu64 -64\(%rax\), %zmm7 +** subq \$256, %rax +** vmovdqu64 128\(%rax\), %zmm6 +** subq \$256, %rsi +** vmovdqu64 64\(%rax\), %zmm5 +** vmovdqu64 \(%rax\), %zmm4 +** subq \$256, %rcx +** vmovdqu64 %zmm7, 192\(%rcx\) +** vmovdqu64 %zmm6, 128\(%rcx\) +** vmovdqu64 %zmm5, 64\(%rcx\) +** vmovdqu64 %zmm4, \(%rcx\) +** cmpq \$256, %rsi +** ja .L11 +** vmovdqu64 %zmm3, \(%rdi\) +** vmovdqu64 %zmm2, 64\(%rdi\) +** vmovdqu64 %zmm1, 128\(%rdi\) +** vmovdqu64 %zmm0, 192\(%rdi\) +** vzeroupper +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_zmm +#include "builtin-memmove-4a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-5a.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-5a.c new file mode 100644 index 0000000..c86defb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-5a.c @@ -0,0 +1,109 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_xmm: +**.LFB0: +** .cfi_startproc +** cmpq \$67, %rdx +** ja .L12 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L12: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$128, %rdx +** jbe .L13 +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L6 +** je .L1 +** movdqu -16\(%rax,%rdx\), %xmm7 +** movdqu -32\(%rax,%rdx\), %xmm6 +** movdqu -48\(%rax,%rdx\), %xmm5 +** movdqu -64\(%rax,%rdx\), %xmm4 +**.L7: +** movdqu \(%rax\), %xmm3 +** subq \$64, %rsi +** addq \$64, %rcx +** addq \$64, %rax +** movdqu -48\(%rax\), %xmm2 +** movdqu -32\(%rax\), %xmm1 +** movdqu -16\(%rax\), %xmm0 +** movups %xmm3, -64\(%rcx\) +** movups %xmm2, -48\(%rcx\) +** movups %xmm1, -32\(%rcx\) +** movups %xmm0, -16\(%rcx\) +** cmpq \$64, %rsi +** ja .L7 +** movups %xmm7, -16\(%rdi,%rdx\) +** movups %xmm6, -32\(%rdi,%rdx\) +** movups %xmm5, -48\(%rdi,%rdx\) +** movups %xmm4, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** movdqu \(%rsi\), %xmm7 +** movdqu 16\(%rsi\), %xmm6 +** movdqu 32\(%rsi\), %xmm5 +** movdqu 48\(%rsi\), %xmm4 +** movdqu -16\(%rsi,%rdx\), %xmm3 +** movdqu -32\(%rsi,%rdx\), %xmm2 +** movdqu -48\(%rsi,%rdx\), %xmm1 +** movdqu -64\(%rsi,%rdx\), %xmm0 +** movups %xmm7, \(%rdi\) +** movups %xmm6, 16\(%rdi\) +** movups %xmm5, 32\(%rdi\) +** movups %xmm4, 48\(%rdi\) +** movups %xmm3, -16\(%rdi,%rdx\) +** movups %xmm2, -32\(%rdi,%rdx\) +** movups %xmm1, -48\(%rdi,%rdx\) +** movups %xmm0, -64\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movdqu \(%rax\), %xmm3 +** movdqu 16\(%rax\), %xmm2 +** leaq \(%rdi,%rdx\), %rcx +** movdqu 32\(%rax\), %xmm1 +** movdqu 48\(%rax\), %xmm0 +** addq %rdx, %rax +**.L8: +** movdqu -16\(%rax\), %xmm7 +** movdqu -32\(%rax\), %xmm6 +** subq \$64, %rsi +** subq \$64, %rcx +** movdqu -48\(%rax\), %xmm5 +** movdqu -64\(%rax\), %xmm4 +** subq \$64, %rax +** movups %xmm7, 48\(%rcx\) +** movups %xmm6, 32\(%rcx\) +** movups %xmm5, 16\(%rcx\) +** movups %xmm4, \(%rcx\) +** cmpq \$64, %rsi +** ja .L8 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, 32\(%rdi\) +** movups %xmm0, 48\(%rdi\) +** ret +** .cfi_endproc +**... +*/ + +#ifndef gcc_memmove +#define gcc_memmove gcc_memmove_xmm +#endif + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n > 67) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-5b.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-5b.c new file mode 100644 index 0000000..e5fc156 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-5b.c @@ -0,0 +1,120 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx512f -march=x86-64-v3 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_ymm: +**.LFB0: +** .cfi_startproc +** cmpq \$67, %rdx +** ja .L14 +**.L12: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L14: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$256, %rdx +** jbe .L15 +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L7 +** je .L12 +** vmovdqu -32\(%rax,%rdx\), %ymm7 +** vmovdqu -64\(%rax,%rdx\), %ymm6 +** vmovdqu -96\(%rax,%rdx\), %ymm5 +** vmovdqu -128\(%rax,%rdx\), %ymm4 +**.L8: +** vmovdqu \(%rax\), %ymm3 +** addq \$-128, %rsi +** subq \$-128, %rcx +** subq \$-128, %rax +** vmovdqu -96\(%rax\), %ymm2 +** vmovdqu -64\(%rax\), %ymm1 +** vmovdqu -32\(%rax\), %ymm0 +** vmovdqu %ymm3, -128\(%rcx\) +** vmovdqu %ymm2, -96\(%rcx\) +** vmovdqu %ymm1, -64\(%rcx\) +** vmovdqu %ymm0, -32\(%rcx\) +** cmpq \$128, %rsi +** ja .L8 +** vmovdqu %ymm7, -32\(%rdi,%rdx\) +** vmovdqu %ymm6, -64\(%rdi,%rdx\) +** vmovdqu %ymm5, -96\(%rdi,%rdx\) +** vmovdqu %ymm4, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L15: +** cmpq \$128, %rdx +** jb .L6 +** vmovdqu \(%rsi\), %ymm7 +** vmovdqu 32\(%rsi\), %ymm6 +** vmovdqu 64\(%rsi\), %ymm5 +** vmovdqu 96\(%rsi\), %ymm4 +** vmovdqu -32\(%rsi,%rdx\), %ymm3 +** vmovdqu -64\(%rsi,%rdx\), %ymm2 +** vmovdqu -96\(%rsi,%rdx\), %ymm1 +** vmovdqu -128\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm7, \(%rdi\) +** vmovdqu %ymm6, 32\(%rdi\) +** vmovdqu %ymm5, 64\(%rdi\) +** vmovdqu %ymm4, 96\(%rdi\) +** vmovdqu %ymm3, -32\(%rdi,%rdx\) +** vmovdqu %ymm2, -64\(%rdi,%rdx\) +** vmovdqu %ymm1, -96\(%rdi,%rdx\) +** vmovdqu %ymm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** vmovdqu \(%rsi\), %ymm3 +** vmovdqu 32\(%rsi\), %ymm2 +** vmovdqu -32\(%rsi,%rdx\), %ymm1 +** vmovdqu -64\(%rsi,%rdx\), %ymm0 +** vmovdqu %ymm3, \(%rdi\) +** vmovdqu %ymm2, 32\(%rdi\) +** vmovdqu %ymm1, -32\(%rdi,%rdx\) +** vmovdqu %ymm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** vmovdqu \(%rax\), %ymm3 +** vmovdqu 32\(%rax\), %ymm2 +** leaq \(%rdi,%rdx\), %rcx +** vmovdqu 64\(%rax\), %ymm1 +** vmovdqu 96\(%rax\), %ymm0 +** addq %rdx, %rax +**.L9: +** vmovdqu -32\(%rax\), %ymm7 +** vmovdqu -64\(%rax\), %ymm6 +** addq \$-128, %rsi +** addq \$-128, %rcx +** vmovdqu -96\(%rax\), %ymm5 +** vmovdqu -128\(%rax\), %ymm4 +** addq \$-128, %rax +** vmovdqu %ymm7, 96\(%rcx\) +** vmovdqu %ymm6, 64\(%rcx\) +** vmovdqu %ymm5, 32\(%rcx\) +** vmovdqu %ymm4, \(%rcx\) +** cmpq \$128, %rsi +** ja .L9 +** vmovdqu %ymm3, \(%rdi\) +** vmovdqu %ymm2, 32\(%rdi\) +** vmovdqu %ymm1, 64\(%rdi\) +** vmovdqu %ymm0, 96\(%rdi\) +** vzeroupper +** ret +** .cfi_endproc +**.LFE0: +**... +*/ + +#define gcc_memmove gcc_memmove_ymm +#include "builtin-memmove-5a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-5c.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-5c.c new file mode 100644 index 0000000..a8443f6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-5c.c @@ -0,0 +1,130 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -mmove-max=512 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove_zmm: +**.LFB0: +** .cfi_startproc +** cmpq \$67, %rdx +** ja .L14 +**.L12: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L14: +** movq %rdi, %rcx +** movq %rsi, %rax +** cmpq \$128, %rdx +** jbe .L15 +** cmpq \$512, %rdx +** ja .L5 +** cmpq \$256, %rdx +** jnb .L16 +** vmovdqu64 \(%rsi\), %zmm3 +** vmovdqu64 64\(%rsi\), %zmm2 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm3, \(%rdi\) +** vmovdqu64 %zmm2, 64\(%rdi\) +** vmovdqu64 %zmm1, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -128\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L15: +** vmovdqu64 \(%rsi\), %zmm1 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm1, \(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movq %rdx, %rsi +** cmpq %rdi, %rax +** jb .L7 +** je .L12 +** vmovdqu64 -64\(%rax,%rdx\), %zmm7 +** vmovdqu64 -128\(%rax,%rdx\), %zmm6 +** vmovdqu64 -192\(%rax,%rdx\), %zmm5 +** vmovdqu64 -256\(%rax,%rdx\), %zmm4 +**.L8: +** vmovdqu64 \(%rax\), %zmm3 +** addq \$256, %rax +** vmovdqu64 -192\(%rax\), %zmm2 +** subq \$256, %rsi +** vmovdqu64 -128\(%rax\), %zmm1 +** vmovdqu64 -64\(%rax\), %zmm0 +** addq \$256, %rcx +** vmovdqu64 %zmm3, -256\(%rcx\) +** vmovdqu64 %zmm2, -192\(%rcx\) +** vmovdqu64 %zmm1, -128\(%rcx\) +** vmovdqu64 %zmm0, -64\(%rcx\) +** cmpq \$256, %rsi +** ja .L8 +** vmovdqu64 %zmm7, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm6, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm5, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm4, -256\(%rdi,%rdx\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** vmovdqu64 \(%rax\), %zmm3 +** leaq \(%rdi,%rdx\), %rcx +** vmovdqu64 64\(%rax\), %zmm2 +** vmovdqu64 128\(%rax\), %zmm1 +** vmovdqu64 192\(%rax\), %zmm0 +** addq %rdx, %rax +**.L9: +** vmovdqu64 -64\(%rax\), %zmm7 +** subq \$256, %rax +** vmovdqu64 128\(%rax\), %zmm6 +** subq \$256, %rsi +** vmovdqu64 64\(%rax\), %zmm5 +** vmovdqu64 \(%rax\), %zmm4 +** subq \$256, %rcx +** vmovdqu64 %zmm7, 192\(%rcx\) +** vmovdqu64 %zmm6, 128\(%rcx\) +** vmovdqu64 %zmm5, 64\(%rcx\) +** vmovdqu64 %zmm4, \(%rcx\) +** cmpq \$256, %rsi +** ja .L9 +** vmovdqu64 %zmm3, \(%rdi\) +** vmovdqu64 %zmm2, 64\(%rdi\) +** vmovdqu64 %zmm1, 128\(%rdi\) +** vmovdqu64 %zmm0, 192\(%rdi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L16: +** vmovdqu64 \(%rsi\), %zmm7 +** vmovdqu64 64\(%rsi\), %zmm6 +** vmovdqu64 -64\(%rsi,%rdx\), %zmm3 +** vmovdqu64 -128\(%rsi,%rdx\), %zmm2 +** vmovdqu64 128\(%rsi\), %zmm5 +** vmovdqu64 192\(%rsi\), %zmm4 +** vmovdqu64 -192\(%rsi,%rdx\), %zmm1 +** vmovdqu64 -256\(%rsi,%rdx\), %zmm0 +** vmovdqu64 %zmm7, \(%rdi\) +** vmovdqu64 %zmm6, 64\(%rdi\) +** vmovdqu64 %zmm5, 128\(%rdi\) +** vmovdqu64 %zmm4, 192\(%rdi\) +** vmovdqu64 %zmm3, -64\(%rdi,%rdx\) +** vmovdqu64 %zmm2, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm1, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -256\(%rdi,%rdx\) +** vzeroupper +** ret +** .cfi_endproc +**... +*/ + +#define gcc_memmove gcc_memmove_zmm +#include "builtin-memmove-5a.c" diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-6.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-6.c new file mode 100644 index 0000000..6d15916 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-6.c @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove: +**.LFB0: +** .cfi_startproc +** cmpq \$7, %rdx +** jbe .L8 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** cmpl \$4, %edx +** jnb .L9 +** cmpl \$1, %edx +** ja .L5 +** jb .L1 +** movzbl \(%rsi\), %eax +** movb %al, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L9: +** movl %edx, %edx +** movl \(%rsi\), %ecx +** movl -4\(%rsi,%rdx\), %eax +** movl %ecx, \(%rdi\) +** movl %eax, -4\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movl %edx, %edx +** movzwl \(%rsi\), %ecx +** movzwl -2\(%rsi,%rdx\), %eax +** movw %cx, \(%rdi\) +** movw %ax, -2\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n < 8) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-7.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-7.c new file mode 100644 index 0000000..4118b13 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-7.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove: +**.LFB0: +** .cfi_startproc +** cmpq \$3, %rdx +** jbe .L7 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** cmpl \$2, %edx +** jnb .L8 +** cmpl \$1, %edx +** jb .L1 +** movzbl \(%rsi\), %eax +** movb %al, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** movl %edx, %edx +** movzwl \(%rsi\), %ecx +** movzwl -2\(%rsi,%rdx\), %eax +** movw %cx, \(%rdi\) +** movw %ax, -2\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n < 4) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-8.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-8.c new file mode 100644 index 0000000..aa57a10 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-8.c @@ -0,0 +1,90 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove: +**.LFB0: +** .cfi_startproc +** cmpq \$33, %rdx +** jbe .L12 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L12: +** cmpl \$16, %edx +** jnb .L13 +** cmpl \$8, %edx +** jnb .L6 +** cmpl \$4, %edx +** jnb .L7 +** cmpl \$1, %edx +** ja .L8 +** jb .L1 +** movzbl \(%rsi\), %eax +** movb %al, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L13: +** cmpl \$32, %edx +** ja .L5 +** movl %edx, %edx +** movdqu \(%rsi\), %xmm1 +** movdqu -16\(%rsi,%rdx\), %xmm0 +** movups %xmm1, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movl %edx, %edx +** movdqu \(%rsi\), %xmm3 +** movdqu 16\(%rsi\), %xmm2 +** addq %rdx, %rsi +** movdqu -16\(%rsi\), %xmm1 +** movdqu -32\(%rsi\), %xmm0 +** movups %xmm3, \(%rdi\) +** movups %xmm2, 16\(%rdi\) +** movups %xmm1, -16\(%rdi,%rdx\) +** movups %xmm0, -32\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movl %edx, %edx +** movq \(%rsi\), %rcx +** movq -8\(%rsi,%rdx\), %rax +** movq %rcx, \(%rdi\) +** movq %rax, -8\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L7: +** movl %edx, %edx +** movl \(%rsi\), %ecx +** movl -4\(%rsi,%rdx\), %eax +** movl %ecx, \(%rdi\) +** movl %eax, -4\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L8: +** movl %edx, %edx +** movzwl \(%rsi\), %ecx +** movzwl -2\(%rsi,%rdx\), %eax +** movw %cx, \(%rdi\) +** movw %ax, -2\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n < 34) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-memmove-9.c b/gcc/testsuite/gcc.target/i386/builtin-memmove-9.c new file mode 100644 index 0000000..f84565e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-memmove-9.c @@ -0,0 +1,63 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-avx -msse2 -mtune=generic -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target { lp64 } } {^\t?\.} } } */ + +/* +**gcc_memmove: +**.LFB0: +** .cfi_startproc +** cmpq \$15, %rdx +** jbe .L9 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L9: +** cmpl \$8, %edx +** jnb .L10 +** cmpl \$4, %edx +** jnb .L5 +** cmpl \$1, %edx +** ja .L6 +** jb .L1 +** movzbl \(%rsi\), %eax +** movb %al, \(%rdi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L10: +** movl %edx, %edx +** movq \(%rsi\), %rcx +** movq -8\(%rsi,%rdx\), %rax +** movq %rcx, \(%rdi\) +** movq %rax, -8\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L5: +** movl %edx, %edx +** movl \(%rsi\), %ecx +** movl -4\(%rsi,%rdx\), %eax +** movl %ecx, \(%rdi\) +** movl %eax, -4\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L6: +** movl %edx, %edx +** movzwl \(%rsi\), %ecx +** movzwl -2\(%rsi,%rdx\), %eax +** movw %cx, \(%rdi\) +** movw %ax, -2\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +void +gcc_memmove (void *a, void *b, __SIZE_TYPE__ n) +{ + if (n < 16) + __builtin_memmove (a, b, n); +} diff --git a/gcc/testsuite/gcc.target/loongarch/and-large-immediate-opt.c b/gcc/testsuite/gcc.target/loongarch/and-large-immediate-opt.c new file mode 100644 index 0000000..921bef6 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/and-large-immediate-opt.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-O3" } */ +/* { dg-final { scan-assembler-not "\tlu12i.w" } } */ +/* { dg-final { scan-assembler-not "\tori" } } */ +/* { dg-final { scan-assembler-not "\tlu52i.d" } } */ +/* { dg-final { scan-assembler-not "\tand" } } */ +/* { dg-final { scan-assembler "\tbstrpick.d" } } */ +/* { dg-final { scan-assembler "\tbstrins.d" } } */ + +long +test (long a) +{ + return a & 0x3fffffffefffffff; +} diff --git a/gcc/testsuite/gcc.target/loongarch/extendsidi2-combine.c b/gcc/testsuite/gcc.target/loongarch/extendsidi2-combine.c new file mode 100644 index 0000000..0c3613c --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/extendsidi2-combine.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-O3 -fno-strict-aliasing" } */ + +int +test (double a) +{ + int z; + + *((double *)&z) = a; + return z; +} + +/* { dg-final { scan-assembler-not "slli\\.w" } } */ diff --git a/gcc/testsuite/gcc.target/loongarch/imm-load.c b/gcc/testsuite/gcc.target/loongarch/imm-load.c index 33291fe..a125840 100644 --- a/gcc/testsuite/gcc.target/loongarch/imm-load.c +++ b/gcc/testsuite/gcc.target/loongarch/imm-load.c @@ -7,5 +7,5 @@ test (void) { return 0x1234567890abcdef; } -/* { dg-final { scan-rtl-dump-times "scanning new insn with uid" 6 "split1" } } */ +/* { dg-final { scan-rtl-dump-times "scanning new insn with uid" 4 "split1" } } */ diff --git a/gcc/testsuite/gcc.target/loongarch/lasx-xvpermi_q-opt.c b/gcc/testsuite/gcc.target/loongarch/lasx-xvpermi_q-opt.c new file mode 100644 index 0000000..16fb9df --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/lasx-xvpermi_q-opt.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mlasx -ftree-vectorize" } */ + +#include <lasxintrin.h> + +#define TEST_FUNC(imm) \ + __m256i \ + test_##imm (__m256i op0, __m256i op1) \ + { \ + return __lasx_xvpermi_q (op0, op1, imm); \ + } + +TEST_FUNC (0x00) +/* { dg-final { scan-assembler-not "test_0x00:.*\txvld.*xvld.*-test_0x00"} } */ +/* { dg-final { scan-assembler-times "test_0x00:.*\txvpermi\\.d.*-test_0x00" 1 } } */ + +TEST_FUNC (0x01) +/* { dg-final { scan-assembler-not "test_0x01:.*\txvld.*xvld.*-test_0x01"} } */ +/* { dg-final { scan-assembler-times "test_0x01:.*\txvpermi\\.d.*-test_0x01" 1 } } */ + +TEST_FUNC (0x10) +/* { dg-final { scan-assembler-not "test_0x10:.*\txvld.*xvld.*-test_0x10"} } */ +/* { dg-final { scan-assembler-not "test_0x10:.*\txvpermi.*-test_0x10"} } */ + +TEST_FUNC (0x11) +/* { dg-final { scan-assembler-not "test_0x11:.*\txvld.*xvld.*-test_0x11"} } */ +/* { dg-final { scan-assembler-times "test_0x11:.*\txvpermi\\.d.*-test_0x11" 1 } } */ + +TEST_FUNC (0x22) +/* { dg-final { scan-assembler-not "test_0x22:.*\txvld.*xvld.*-test_0x22"} } */ +/* { dg-final { scan-assembler-times "test_0x22:.*\txvpermi\\.d.*-test_0x22" 1 } } */ + +TEST_FUNC (0x23) +/* { dg-final { scan-assembler-not "test_0x23:.*\txvld.*xvld.*-test_0x23"} } */ +/* { dg-final { scan-assembler-times "test_0x23:.*\txvpermi\\.d.*-test_0x23" 1 } } */ + +TEST_FUNC (0x32) +/* { dg-final { scan-assembler-not "test_0x32:.*\txvld.*xvld.*-test_0x32"} } */ +/* { dg-final { scan-assembler-not "test_0x32:.*\txvpermi.*-test_0x32"} } */ + +TEST_FUNC (0x33) +/* { dg-final { scan-assembler-not "test_0x33:.*\txvld.*xvld.*-test_0x33"} } */ +/* { dg-final { scan-assembler-times "test_0x33:.*\txvpermi\\.d.*-test_0x33" 1 } } */ + diff --git a/gcc/testsuite/gcc.target/loongarch/mem-and-mask-opt.c b/gcc/testsuite/gcc.target/loongarch/mem-and-mask-opt.c new file mode 100644 index 0000000..9b3a5cd --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/mem-and-mask-opt.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ +/* { dg-final { scan-assembler-not "bstrpick" } } */ +/* { dg-final { scan-assembler "ld\\.wu" } } */ + +struct st +{ + char const *name; +}; +struct fst +{ + struct st *groups; +}; + +struct fst *pfunc (int); + +const char * +test (int pc, unsigned group) +{ + struct fst *pci = pfunc (pc); + + return pci->groups[group].name; +} diff --git a/gcc/testsuite/gcc.target/loongarch/mode-tieable-opt.c b/gcc/testsuite/gcc.target/loongarch/mode-tieable-opt.c new file mode 100644 index 0000000..d6a6577 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/mode-tieable-opt.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-O3 -mno-lsx" } */ +/* { dg-final { scan-assembler-not "stptr\.d" } } */ +/* { dg-final { scan-assembler-not "fld\.d" } } */ +/* { dg-final { scan-assembler-not "fst\.d" } } */ +/* { dg-final { scan-assembler-not "ldptr\.d" } } */ +/* { dg-final { scan-assembler "movgr2fr\.d" } } */ +/* { dg-final { scan-assembler "movfr2gr\.d" } } */ + +typedef double vec __attribute__ ((vector_size(16))); + +vec +foo (vec x, double a) +{ + x[0] -= a; + return x; +} diff --git a/gcc/testsuite/gcc.target/loongarch/mulh_wu.c b/gcc/testsuite/gcc.target/loongarch/mulh_wu.c new file mode 100644 index 0000000..53fc518 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/mulh_wu.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-O3 -mabi=lp64d" } */ +/* { dg-final { scan-assembler "\tmulh.wu" } } */ +/* { dg-final { scan-assembler-not "\tlu32i.d" } } */ + +unsigned int +test (unsigned int *a) +{ + return *a / 60; +} diff --git a/gcc/testsuite/gcc.target/loongarch/spill-less.c b/gcc/testsuite/gcc.target/loongarch/spill-less.c new file mode 100644 index 0000000..77eb9b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/spill-less.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-O3 -fno-strict-aliasing" } */ + +double +convert (long long in) +{ + double f; + *((long long *)&f) = in; + return f; +} + +/* { dg-final { scan-assembler-not "st\\.d" } } */ +/* { dg-final { scan-assembler-not "fld\\.d" } } */ +/* { dg-final { scan-assembler "movgr2fr\\.d" } } */ diff --git a/gcc/testsuite/gcc.target/loongarch/vec_pack_unpack_256.c b/gcc/testsuite/gcc.target/loongarch/vec_pack_unpack_256.c index 506b7bd..5b2fd9b 100644 --- a/gcc/testsuite/gcc.target/loongarch/vec_pack_unpack_256.c +++ b/gcc/testsuite/gcc.target/loongarch/vec_pack_unpack_256.c @@ -55,7 +55,8 @@ test_vec_unpacks_float_hi_lo_v8si (void) } /* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8si:.*\tvext2xv\\.d\\.w.*-test_vec_unpacks_hi_lo_v8si" } } */ -/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8si:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v8si" } } */ +/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8si:.*\txvpermi\\.d.*-test_vec_unpacks_hi_lo_v8si" } } */ +/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v8si:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v8si" } } */ void test_vec_unpacks_hi_lo_v8si (void) { @@ -64,7 +65,8 @@ test_vec_unpacks_hi_lo_v8si (void) } /* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v16hi:.*\tvext2xv\\.w\\.h.*-test_vec_unpacks_hi_lo_v16hi" } } */ -/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v16hi:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v16hi" } } */ +/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v16hi:.*\txvpermi\\.d.*-test_vec_unpacks_hi_lo_v16hi" } } */ +/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v16hi:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v16hi" } } */ void test_vec_unpacks_hi_lo_v16hi (void) { @@ -73,7 +75,8 @@ test_vec_unpacks_hi_lo_v16hi (void) } /* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v32qi:.*\tvext2xv\\.h\\.b.*-test_vec_unpacks_hi_lo_v32qi" } } */ -/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v32qi:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v32qi" } } */ +/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v32qi:.*\txvpermi\\.d.*-test_vec_unpacks_hi_lo_v32qi" } } */ +/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v32qi:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v32qi" } } */ void test_vec_unpacks_hi_lo_v32qi (void) { @@ -91,7 +94,8 @@ test_vec_unpacks_hi_lo_v8sf (void) } /* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v8si:.*\tvext2xv\\.du\\.wu.*-test_vec_unpacku_hi_lo_v8si" } } */ -/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v8si:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v8si" } } */ +/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v8si:.*\txvpermi\\.d.*-test_vec_unpacku_hi_lo_v8si" } } */ +/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v8si:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v8si" } } */ void test_vec_unpacku_hi_lo_v8si (void) { @@ -100,7 +104,8 @@ test_vec_unpacku_hi_lo_v8si (void) } /* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v16hi:.*\tvext2xv\\.wu\\.hu.*-test_vec_unpacku_hi_lo_v16hi" } } */ -/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v16hi:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v16hi" } } */ +/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v16hi:.*\txvpermi\\.d.*-test_vec_unpacku_hi_lo_v16hi" } } */ +/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v16hi:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v16hi" } } */ void test_vec_unpacku_hi_lo_v16hi (void) { @@ -109,7 +114,8 @@ test_vec_unpacku_hi_lo_v16hi (void) } /* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v32qi:.*\tvext2xv\\.hu\\.bu.*-test_vec_unpacku_hi_lo_v32qi" } } */ -/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v32qi:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v32qi" } } */ +/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v32qi:.*\txvpermi\\.d.*-test_vec_unpacku_hi_lo_v32qi" } } */ +/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v32qi:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v32qi" } } */ void test_vec_unpacku_hi_lo_v32qi (void) { diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c index 64ff870..3f34a43 100644 --- a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c @@ -3301,7 +3301,7 @@ __lasx_vext2xv_du_bu (v32i8 _1) v32i8 __lasx_xvpermi_q (v32i8 _1, v32i8 _2) { - return __builtin_lasx_xvpermi_q (_1, _2, 1); + return __builtin_lasx_xvpermi_q (_1, _2, 0x20); } v4i64 __lasx_xvpermi_d (v4i64 _1) diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-concat-128-256-result.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-concat-128-256-result.c new file mode 100644 index 0000000..e876c4a --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-concat-128-256-result.c @@ -0,0 +1,68 @@ +/* { dg-options "-mabi=lp64d -O2 -mlasx -w -fno-strict-aliasing" } */ + +#include "../simd_correctness_check.h" +#include <lasxintrin.h> + +int +main () +{ + __m128i __m128i_op0, __m128i_op1, __m128i_op2, __m128i_out, __m128i_result; + __m128 __m128_op0, __m128_op1, __m128_op2, __m128_out, __m128_result; + __m128d __m128d_op0, __m128d_op1, __m128d_op2, __m128d_out, __m128d_result; + + __m256i __m256i_op0, __m256i_op1, __m256i_op2, __m256i_out, __m256i_result; + __m256 __m256_op0, __m256_op1, __m256_op2, __m256_out, __m256_result; + __m256d __m256d_op0, __m256d_op1, __m256d_op2, __m256d_out, __m256d_result; + + //__m128_op0={1,2,3,4},__m128_op1={5,6,7,8}; + *((int *)&__m128_op0[3]) = 0x40800000; + *((int *)&__m128_op0[2]) = 0x40400000; + *((int *)&__m128_op0[1]) = 0x40000000; + *((int *)&__m128_op0[0]) = 0x3f800000; + *((int *)&__m128_op1[3]) = 0x41000000; + *((int *)&__m128_op1[2]) = 0x40e00000; + *((int *)&__m128_op1[1]) = 0x40c00000; + *((int *)&__m128_op1[0]) = 0x40a00000; + *((int *)&__m256_result[7]) = 0x41000000; + *((int *)&__m256_result[6]) = 0x40e00000; + *((int *)&__m256_result[5]) = 0x40c00000; + *((int *)&__m256_result[4]) = 0x40a00000; + *((int *)&__m256_result[3]) = 0x40800000; + *((int *)&__m256_result[2]) = 0x40400000; + *((int *)&__m256_result[1]) = 0x40000000; + *((int *)&__m256_result[0]) = 0x3f800000; + __m256_out = __lasx_concat_128_s (__m128_op0, __m128_op1); + ASSERTEQ_32 (__LINE__, __m256_result, __m256_out); + __m256_out = __lasx_cast_128_s (__m128_op0); + ASSERTEQ_32 (__LINE__, __m256_out, __m128_op0); + + //__m128i_op0={1,2},__m128i_op1={3,4}; + *((unsigned long *)&__m128i_op0[1]) = 0x2; + *((unsigned long *)&__m128i_op0[0]) = 0x1; + *((unsigned long *)&__m128i_op1[1]) = 0x4; + *((unsigned long *)&__m128i_op1[0]) = 0x3; + *((unsigned long *)&__m256i_result[3]) = 0x4; + *((unsigned long *)&__m256i_result[2]) = 0x3; + *((unsigned long *)&__m256i_result[1]) = 0x2; + *((unsigned long *)&__m256i_result[0]) = 0x1; + __m256i_out = __lasx_concat_128 (__m128i_op0, __m128i_op1); + ASSERTEQ_64 (__LINE__, __m256i_result, __m256i_out); + __m256i_out = __lasx_cast_128 (__m128i_op0); + ASSERTEQ_64 (__LINE__, __m256i_out, __m128i_op0); + + //__m128d_op0={1,2},__m128i_op1={3,4}; + *((unsigned long *)&__m128d_op0[1]) = 0x4000000000000000; + *((unsigned long *)&__m128d_op0[0]) = 0x3ff0000000000000; + *((unsigned long *)&__m128d_op1[1]) = 0x4010000000000000; + *((unsigned long *)&__m128d_op1[0]) = 0x4008000000000000; + *((unsigned long *)&__m256d_result[3]) = 0x4010000000000000; + *((unsigned long *)&__m256d_result[2]) = 0x4008000000000000; + *((unsigned long *)&__m256d_result[1]) = 0x4000000000000000; + *((unsigned long *)&__m256d_result[0]) = 0x3ff0000000000000; + __m256d_out = __lasx_concat_128_d (__m128d_op0, __m128d_op1); + ASSERTEQ_64 (__LINE__, __m256d_result, __m256d_out); + __m256d_out = __lasx_cast_128_d (__m128d_op0); + ASSERTEQ_64 (__LINE__, __m256d_out, __m128d_op0); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-concat-128-256.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-concat-128-256.c new file mode 100644 index 0000000..5d8cbb2 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-concat-128-256.c @@ -0,0 +1,92 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-mabi=lp64d -O2 -mlasx" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include <lasxintrin.h> + +/* +**foo1: +** vinsgr2vr.d (\$vr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r6,1 +** vinsgr2vr.d (\$vr[0-9]+),\$r8,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x02 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256 +foo1 (__m128 x, __m128 y) +{ + return __builtin_lasx_concat_128_s (x, y); +} + +/* +**foo2: +** vinsgr2vr.d (\$vr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r6,1 +** vinsgr2vr.d (\$vr[0-9]+),\$r8,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x02 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256d +foo2 (__m128d x, __m128d y) +{ + return __builtin_lasx_concat_128_d (x, y); +} + +/* +**foo3: +** vinsgr2vr.d (\$vr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r6,1 +** vinsgr2vr.d (\$vr[0-9]+),\$r8,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x02 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256i +foo3 (__m128i x, __m128i y) +{ + return __builtin_lasx_concat_128 (x, y); +} + +/* +**foo4: +** vinsgr2vr.d (\$vr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r6,1 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256 +foo4 (__m128 x) +{ + return __builtin_lasx_cast_128_s (x); +} + +/* +**foo5: +** vinsgr2vr.d (\$vr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r6,1 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256d +foo5 (__m128d x) +{ + return __builtin_lasx_cast_128_d (x); +} + +/* +**foo6: +** vinsgr2vr.d (\$vr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r6,1 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256i +foo6 (__m128i x) +{ + return __builtin_lasx_cast_128 (x); +} diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128-result.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128-result.c new file mode 100644 index 0000000..61064d6 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128-result.c @@ -0,0 +1,69 @@ +/* { dg-options "-mabi=lp64d -O2 -mlasx -w -fno-strict-aliasing" } */ + +#include "../simd_correctness_check.h" +#include <lasxintrin.h> + +extern void abort (void); +int +main () +{ + __m128i __m128i_result0, __m128i_result1, __m128i_out, __m128i_result; + __m128 __m128_result0, __m128_result1, __m128_out, __m128_result; + __m128d __m128d_result0, __m128d_result1, __m128d_out, __m128d_result; + + __m256i __m256i_op0, __m256i_op1, __m256i_op2, __m256i_out, __m256i_result; + __m256 __m256_op0, __m256_op1, __m256_op2, __m256_out, __m256_result; + __m256d __m256d_op0, __m256d_op1, __m256d_op2, __m256d_out, __m256d_result; + + //__m256_op0 = {1,2,3,4,5,6,7,8}; + *((int *)&__m256_op0[7]) = 0x41000000; + *((int *)&__m256_op0[6]) = 0x40e00000; + *((int *)&__m256_op0[5]) = 0x40c00000; + *((int *)&__m256_op0[4]) = 0x40a00000; + *((int *)&__m256_op0[3]) = 0x40800000; + *((int *)&__m256_op0[2]) = 0x40400000; + *((int *)&__m256_op0[1]) = 0x40000000; + *((int *)&__m256_op0[0]) = 0x3f800000; + *((int *)&__m128_result1[3]) = 0x41000000; + *((int *)&__m128_result1[2]) = 0x40e00000; + *((int *)&__m128_result1[1]) = 0x40c00000; + *((int *)&__m128_result1[0]) = 0x40a00000; + *((int *)&__m128_result0[3]) = 0x40800000; + *((int *)&__m128_result0[2]) = 0x40400000; + *((int *)&__m128_result0[1]) = 0x40000000; + *((int *)&__m128_result0[0]) = 0x3f800000; + __m128_out = __lasx_extract_128_lo_s (__m256_op0); + ASSERTEQ_32 (__LINE__, __m128_result0, __m128_out); + __m128_out = __lasx_extract_128_hi_s (__m256_op0); + ASSERTEQ_32 (__LINE__, __m128_result1, __m128_out); + + //__m256i_op0 = {1,2,3,4}; + *((unsigned long *)&__m256i_op0[3]) = 0x4; + *((unsigned long *)&__m256i_op0[2]) = 0x3; + *((unsigned long *)&__m256i_op0[1]) = 0x2; + *((unsigned long *)&__m256i_op0[0]) = 0x1; + *((unsigned long *)&__m128i_result0[1]) = 0x2; + *((unsigned long *)&__m128i_result0[0]) = 0x1; + *((unsigned long *)&__m128i_result1[1]) = 0x4; + *((unsigned long *)&__m128i_result1[0]) = 0x3; + __m128i_out = __lasx_extract_128_lo (__m256i_op0); + ASSERTEQ_64 (__LINE__, __m128i_result0, __m128i_out); + __m128i_out = __lasx_extract_128_hi (__m256i_op0); + ASSERTEQ_64 (__LINE__, __m128i_result1, __m128i_out); + + //__m256d_op0 = {1,2,3,4}; + *((unsigned long *)&__m256d_op0[3]) = 0x4010000000000000; + *((unsigned long *)&__m256d_op0[2]) = 0x4008000000000000; + *((unsigned long *)&__m256d_op0[1]) = 0x4000000000000000; + *((unsigned long *)&__m256d_op0[0]) = 0x3ff0000000000000; + *((unsigned long *)&__m128d_result0[1]) = 0x4000000000000000; + *((unsigned long *)&__m128d_result0[0]) = 0x3ff0000000000000; + *((unsigned long *)&__m128d_result1[1]) = 0x4010000000000000; + *((unsigned long *)&__m128d_result1[0]) = 0x4008000000000000; + __m128d_out = __lasx_extract_128_lo_d (__m256d_op0); + ASSERTEQ_64 (__LINE__, __m128d_result0, __m128d_out); + __m128d_out = __lasx_extract_128_hi_d (__m256d_op0); + ASSERTEQ_64 (__LINE__, __m128d_result1, __m128d_out); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128.c new file mode 100644 index 0000000..d2219ea --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128.c @@ -0,0 +1,86 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-mabi=lp64d -O2 -mlasx" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include <lasxintrin.h> + +/* +**foo1_lo: +** vld (\$vr[0-9]+),\$r4,0 +** vpickve2gr.du \$r4,(\$vr[0-9]+),0 +** vpickve2gr.du \$r5,(\$vr[0-9]+),1 +** jr \$r1 +*/ +__m128 +foo1_lo (__m256 x) +{ + return __lasx_extract_128_lo_s (x); +} + +/* +**foo1_hi: +** xvld (\$xr[0-9]+),\$r4,0 +** xvpermi.d (\$xr[0-9]+),(\$xr[0-9]+),0xe +** vpickve2gr.du \$r4,(\$vr[0-9]+),0 +** vpickve2gr.du \$r5,(\$vr[0-9]+),1 +** jr \$r1 +*/ +__m128 +foo1_hi (__m256 x) +{ + return __lasx_extract_128_hi_s (x); +} + +/* +**foo2_lo: +** vld (\$vr[0-9]+),\$r4,0 +** vpickve2gr.du \$r4,(\$vr[0-9]+),0 +** vpickve2gr.du \$r5,(\$vr[0-9]+),1 +** jr \$r1 +*/ +__m128d +foo2_lo (__m256d x) +{ + return __lasx_extract_128_lo_d (x); +} + +/* +**foo2_hi: +** xvld (\$xr[0-9]+),\$r4,0 +** xvpermi.d (\$xr[0-9]+),(\$xr[0-9]+),0xe +** vpickve2gr.du \$r4,(\$vr[0-9]+),0 +** vpickve2gr.du \$r5,(\$vr[0-9]+),1 +** jr \$r1 +*/ +__m128d +foo2_hi (__m256d x) +{ + return __lasx_extract_128_hi_d (x); +} + +/* +**foo3_lo: +** vld (\$vr[0-9]+),\$r4,0 +** vpickve2gr.du \$r4,(\$vr[0-9]+),0 +** vpickve2gr.du \$r5,(\$vr[0-9]+),1 +** jr \$r1 +*/ +__m128i +foo3_lo (__m256i x) +{ + return __lasx_extract_128_lo (x); +} + +/* +**foo3_hi: +** xvld (\$xr[0-9]+),\$r4,0 +** xvpermi.d (\$xr[0-9]+),(\$xr[0-9]+),0xe +** vpickve2gr.du \$r4,(\$vr[0-9]+),0 +** vpickve2gr.du \$r5,(\$vr[0-9]+),1 +** jr \$r1 +*/ +__m128i +foo3_hi (__m256i x) +{ + return __lasx_extract_128_hi (x); +} diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-insert-128-256-result.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-insert-128-256-result.c new file mode 100644 index 0000000..ce5abf9 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-insert-128-256-result.c @@ -0,0 +1,97 @@ +/* { dg-options "-mabi=lp64d -O2 -mlasx -w -fno-strict-aliasing" } */ + +#include "../simd_correctness_check.h" +#include <lasxintrin.h> + +extern void abort (void); +int +main () +{ + __m128i __m128i_op0, __m128i_op1, __m128i_out; + __m128 __m128_op0, __m128_op1, __m128_out; + __m128d __m128d_op0, __m128d_op1, __m128d_out; + + __m256i __m256i_op0, __m256i_result0, __m256i_result1, __m256i_out; + __m256 __m256_op0, __m256_result0, __m256_result1, __m256_out; + __m256d __m256d_op0, __m256d_result0, __m256d_result1, __m256d_out; + + //__m256_op0 = {1,2,3,4,5,6,7,8}, __m128_op0 ={9,9,9,9}; + *((int *)&__m256_op0[7]) = 0x41000000; + *((int *)&__m256_op0[6]) = 0x40e00000; + *((int *)&__m256_op0[5]) = 0x40c00000; + *((int *)&__m256_op0[4]) = 0x40a00000; + *((int *)&__m256_op0[3]) = 0x40800000; + *((int *)&__m256_op0[2]) = 0x40400000; + *((int *)&__m256_op0[1]) = 0x40000000; + *((int *)&__m256_op0[0]) = 0x3f800000; + *((int *)&__m128_op0[3]) = 0x41100000; + *((int *)&__m128_op0[2]) = 0x41100000; + *((int *)&__m128_op0[1]) = 0x41100000; + *((int *)&__m128_op0[0]) = 0x41100000; + *((int *)&__m256_result0[7]) = 0x41000000; + *((int *)&__m256_result0[6]) = 0x40e00000; + *((int *)&__m256_result0[5]) = 0x40c00000; + *((int *)&__m256_result0[4]) = 0x40a00000; + *((int *)&__m256_result0[3]) = 0x41100000; + *((int *)&__m256_result0[2]) = 0x41100000; + *((int *)&__m256_result0[1]) = 0x41100000; + *((int *)&__m256_result0[0]) = 0x41100000; + *((int *)&__m256_result1[7]) = 0x41100000; + *((int *)&__m256_result1[6]) = 0x41100000; + *((int *)&__m256_result1[5]) = 0x41100000; + *((int *)&__m256_result1[4]) = 0x41100000; + *((int *)&__m256_result1[3]) = 0x40800000; + *((int *)&__m256_result1[2]) = 0x40400000; + *((int *)&__m256_result1[1]) = 0x40000000; + *((int *)&__m256_result1[0]) = 0x3f800000; + __m256_out = __lasx_insert_128_lo_s (__m256_op0, __m128_op0); + ASSERTEQ_32 (__LINE__, __m256_result0, __m256_out); + __m256_out = __lasx_insert_128_hi_s (__m256_op0, __m128_op0); + ASSERTEQ_32 (__LINE__, __m256_result1, __m256_out); + + //__m256i_op0 ={1,2,3,4},__m128i_op0={5,6},__m128i_op1={7,8}; + *((unsigned long *)&__m256i_op0[3]) = 0x4; + *((unsigned long *)&__m256i_op0[2]) = 0x3; + *((unsigned long *)&__m256i_op0[1]) = 0x2; + *((unsigned long *)&__m256i_op0[0]) = 0x1; + *((unsigned long *)&__m128i_op0[1]) = 0x6; + *((unsigned long *)&__m128i_op0[0]) = 0x5; + *((unsigned long *)&__m128i_op1[1]) = 0x8; + *((unsigned long *)&__m128i_op1[0]) = 0x7; + *((unsigned long *)&__m256i_result0[3]) = 0x4; + *((unsigned long *)&__m256i_result0[2]) = 0x3; + *((unsigned long *)&__m256i_result0[1]) = 0x6; + *((unsigned long *)&__m256i_result0[0]) = 0x5; + *((unsigned long *)&__m256i_result1[3]) = 0x8; + *((unsigned long *)&__m256i_result1[2]) = 0x7; + *((unsigned long *)&__m256i_result1[1]) = 0x2; + *((unsigned long *)&__m256i_result1[0]) = 0x1; + __m256i_out = __lasx_insert_128_lo (__m256i_op0, __m128i_op0); + ASSERTEQ_64 (__LINE__, __m256i_result0, __m256i_out); + __m256i_out = __lasx_insert_128_hi (__m256i_op0, __m128i_op1); + ASSERTEQ_64 (__LINE__, __m256i_result1, __m256i_out); + + //__m256d_op0 ={1,2,3,4},__m128d_op0={5,6},__m128d_op1={7,8}; + *((unsigned long *)&__m256d_op0[3]) = 0x4010000000000000; + *((unsigned long *)&__m256d_op0[2]) = 0x4008000000000000; + *((unsigned long *)&__m256d_op0[1]) = 0x4000000000000000; + *((unsigned long *)&__m256d_op0[0]) = 0x3ff0000000000000; + *((unsigned long *)&__m128d_op0[1]) = 0x4018000000000000; + *((unsigned long *)&__m128d_op0[0]) = 0x4014000000000000; + *((unsigned long *)&__m128d_op1[1]) = 0x4020000000000000; + *((unsigned long *)&__m128d_op1[0]) = 0x401c000000000000; + *((unsigned long *)&__m256d_result0[3]) = 0x4010000000000000; + *((unsigned long *)&__m256d_result0[2]) = 0x4008000000000000; + *((unsigned long *)&__m256d_result0[1]) = 0x4018000000000000; + *((unsigned long *)&__m256d_result0[0]) = 0x4014000000000000; + *((unsigned long *)&__m256d_result1[3]) = 0x4020000000000000; + *((unsigned long *)&__m256d_result1[2]) = 0x401c000000000000; + *((unsigned long *)&__m256d_result1[1]) = 0x4000000000000000; + *((unsigned long *)&__m256d_result1[0]) = 0x3ff0000000000000; + __m256d_out = __lasx_insert_128_lo_d (__m256d_op0, __m128d_op0); + ASSERTEQ_64 (__LINE__, __m256d_result0, __m256d_out); + __m256d_out = __lasx_insert_128_hi_d (__m256d_op0, __m128d_op1); + ASSERTEQ_64 (__LINE__, __m256d_result1, __m256d_out); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-insert-128-256.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-insert-128-256.c new file mode 100644 index 0000000..326c855 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-insert-128-256.c @@ -0,0 +1,95 @@ +/* { dg-do compile { target { loongarch64*-*-* } } } */ +/* { dg-options "-mabi=lp64d -O2 -mlasx" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include <lasxintrin.h> + +/* +**foo1: +** vinsgr2vr.d (\$vr[0-9]+),\$r6,0 +** xvld (\$xr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x30 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256 +foo1 (__m256 x, __m128 y) +{ + return __builtin_lasx_insert_128_lo_s (x, y); +} + +/* +**foo2: +** vinsgr2vr.d (\$vr[0-9]+),\$r6,0 +** xvld (\$xr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x02 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256 +foo2 (__m256 x, __m128 y) +{ + return __builtin_lasx_insert_128_hi_s (x, y); +} + +/* +**foo3: +** vinsgr2vr.d (\$vr[0-9]+),\$r6,0 +** xvld (\$xr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x30 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256d +foo3 (__m256d x, __m128d y) +{ + return __builtin_lasx_insert_128_lo_d (x, y); +} + +/* +**foo4: +** vinsgr2vr.d (\$vr[0-9]+),\$r6,0 +** xvld (\$xr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x02 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256d +foo4 (__m256d x, __m128d y) +{ + return __builtin_lasx_insert_128_hi_d (x, y); +} + +/* +**foo5: +** vinsgr2vr.d (\$vr[0-9]+),\$r6,0 +** xvld (\$xr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x30 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256i +foo5 (__m256i x, __m128i y) +{ + return __builtin_lasx_insert_128_lo (x, y); +} + +/* +**foo6: +** vinsgr2vr.d (\$vr[0-9]+),\$r6,0 +** xvld (\$xr[0-9]+),\$r5,0 +** vinsgr2vr.d (\$vr[0-9]+),\$r7,1 +** xvpermi.q (\$xr[0-9]+),(\$xr[0-9]+),0x02 +** xvst (\$xr[0-9]+),\$r4,0 +** jr \$r1 +*/ +__m256i +foo6 (__m256i x, __m128i y) +{ + return __builtin_lasx_insert_128_hi (x, y); +} diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-1.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-1.c new file mode 100644 index 0000000..4cea38e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Su2e_1f { + union { + struct { + } e1, e2; + } u; + float f; +}; +struct Su2e_1f echo_Su2e_1f(int i, float f, struct Su2e_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-2.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-2.c new file mode 100644 index 0000000..e7271e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Su2e_2f { + union { + struct { + } e1, e2; + } u; + float f; + float g; +}; +struct Su2e_2f echo_Su2e_2f(int i, float f, struct Su2e_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-3.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-3.c new file mode 100644 index 0000000..9743d4a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smu2e_1f { + union { + struct { + } e1, e2; + } u1; + struct { + float f; + union { + struct { + } e1, e2; + } u; + } ue; + union { + struct { + } e1, e2; + } u2; +}; +struct Smu2e_1f echo_Smu2e_1f(int i, float f, struct Smu2e_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-4.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-4.c new file mode 100644 index 0000000..081ea68 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct+union-4.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smu2e_2f { + union { + struct { + } e1, e2; + } u1; + struct { + float f; + float g; + union { + struct { + } e1, e2; + } u; + } ue; + union { + struct { + } e1, e2; + } u2; +}; +struct Smu2e_2f echo_Smu2e_2f(int i, float f, struct Smu2e_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-1.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-1.c new file mode 100644 index 0000000..a0a4866 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Se_1f { + struct { + } e1; + float f; +}; +struct Se_1f echo_Se_1f(int i, float f, struct Se_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-10.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-10.c new file mode 100644 index 0000000..de8ad02 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-10.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S1ae_2f { + struct { + } e1[1]; + float f; + float g; +}; +struct S1ae_2f echo_S1ae_2f(int i, float f, struct S1ae_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-11.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-11.c new file mode 100644 index 0000000..c99bb22 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-11.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm1ae_1f { + struct { + } e1[1]; + struct { + float f; + struct { + } e[1]; + } fe; + struct { + } e2[1]; +}; +struct Sm1ae_1f echo_Sm1ae_1f(int i, float f, struct Sm1ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-12.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-12.c new file mode 100644 index 0000000..065ff02 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-12.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm1ae_2f { + struct { + } e1[1]; + struct { + float f; + float g; + struct { + } e[1]; + } fe; + struct { + } e2[1]; +}; +struct Sm1ae_2f echo_Sm1ae_2f(int i, float f, struct Sm1ae_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-2.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-2.c new file mode 100644 index 0000000..93210fe --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Se_2f { + struct { + } e1; + float f; + float g; +}; +struct Se_2f echo_Se_2f(int i, float f, struct Se_2f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-3.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-3.c new file mode 100644 index 0000000..b8c3362 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-3.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sme_1f { + struct { + } e1; + struct { + float f; + struct { + } e; + } fe; + struct { + } e2; +}; +struct Sme_1f echo_Sme_1f(int i, float f, struct Sme_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-4.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-4.c new file mode 100644 index 0000000..0ce36d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-4.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sme_2f { + struct { + } e1; + struct { + float f; + float g; + struct { + } e; + } fe; + struct { + } e2; +}; +struct Sme_2f echo_Sme_2f(int i, float f, struct Sme_2f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-5.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-5.c new file mode 100644 index 0000000..0ae1e41 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-5.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S0ae_1f { + struct { + } e1[0]; + float f; +}; +struct S0ae_1f echo_S0ae_1f(int i, float f, struct S0ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-6.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-6.c new file mode 100644 index 0000000..d3d0b65 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-6.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S0ae_2f { + struct { + } e1[0]; + float f; + float g; +}; +struct S0ae_2f echo_S0ae_2f(int i, float f, struct S0ae_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-7.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-7.c new file mode 100644 index 0000000..9eae13d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-7.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm0ae_1f { + struct { + } e1[0]; + struct { + float f; + struct { + } e[0]; + } fe; + struct { + } e2[0]; +}; +struct Sm0ae_1f echo_Sm0ae_1f(int i, float f, struct Sm0ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-8.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-8.c new file mode 100644 index 0000000..e7c81f4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-8.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Sm0ae_2f { + struct { + } e1[0]; + struct { + float f; + float g; + struct { + } e[0]; + } fe; + struct { + } e2[0]; +}; +struct Sm0ae_2f echo_Sm0ae_2f(int i, float f, struct Sm0ae_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-struct-9.c b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-9.c new file mode 100644 index 0000000..55c4be4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-struct-9.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S1ae_1f { + struct { + } e1[1]; + float f; +}; +struct S1ae_1f echo_S1ae_1f(int i, float f, struct S1ae_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-union-1.c b/gcc/testsuite/gcc.target/riscv/abi/empty-union-1.c new file mode 100644 index 0000000..17beb0d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-union-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Seu_1f { + union { + } e1; + float f; +}; +struct Seu_1f echo_Seu_1f(int i, float f, struct Seu_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-union-2.c b/gcc/testsuite/gcc.target/riscv/abi/empty-union-2.c new file mode 100644 index 0000000..c583186 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-union-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct S2eu_2f { + union { + } e1; + float f; + float g; +}; +struct S2eu_2f echo_S2eu_2f(int i, float f, struct S2eu_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-union-3.c b/gcc/testsuite/gcc.target/riscv/abi/empty-union-3.c new file mode 100644 index 0000000..e9e189b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-union-3.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smeu_1f { + union { + } e1; + struct { + float f; + union { + } e; + } fe; + union { + } e2; +}; +struct Smeu_1f echo_Smeu_1f(int i, float f, struct Smeu_1f s) { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/abi/empty-union-4.c b/gcc/testsuite/gcc.target/riscv/abi/empty-union-4.c new file mode 100644 index 0000000..91c2d89 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/abi/empty-union-4.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g -mabi=lp64d -fdump-rtl-expand" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct Smeu_2f { + union { + } e1; + struct { + float f; + float g; + union { + } e; + } fe; + union { + } e2; +}; +struct Smeu_2f echo_Smeu_2f(int i, float f, struct Smeu_2f s) /* { dg-warning "ABI for flattened empty union and zero length array changed in GCC 16" } */ { + return s; +} + +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa1 \[ s \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ .*\)[[:space:]]+\(reg.*:SF \d+ fa2 \[ s\+4 \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa0\)[[:space:]]+\(reg.*:SF \d+ \[ <retval> \]\)\)} "expand" } } */ +/* { dg-final { scan-rtl-dump {\(set \(reg.*:SF \d+ fa1\)[[:space:]]+\(reg.*:SF \d+ \[ <retval>\+4 \]\)\)} "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/pr52345.c b/gcc/testsuite/gcc.target/riscv/pr52345.c new file mode 100644 index 0000000..90feb91 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr52345.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gcbv_zicond -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-O2 -march=rv32gcbv_zicond -mabi=ilp32" { target { rv32 } } } */ + +int f(int a, int b) +{ + int c = a != 0; + int d = (c!=0|b!=0); + return d; +} + +int h (int a, int b) +{ + int c = (a!=0|b); + int d = c==0; + return d; +} + +/* { dg-final { scan-assembler-times {\tor} 2 } } */ +/* { dg-final { scan-assembler-times {\tsnez} 1 } } */ +/* { dg-final { scan-assembler-times {\tseqz} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/riscv.exp b/gcc/testsuite/gcc.target/riscv/riscv.exp index b5e7618..dd8443d 100644 --- a/gcc/testsuite/gcc.target/riscv/riscv.exp +++ b/gcc/testsuite/gcc.target/riscv/riscv.exp @@ -42,6 +42,8 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/sched1-spills/*.{\[cS\], "" $DEFAULT_CFLAGS gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/xandes/*.\[cS\]]] \ "" $DEFAULT_CFLAGS +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/abi/*.\[cS\]]] \ + "" $DEFAULT_CFLAGS # Saturation alu foreach opt { diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod new file mode 100644 index 0000000..63fd338 --- /dev/null +++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport2.mod @@ -0,0 +1,12 @@ + +(* { dg-do compile } *) +(* { dg-options "-g -c" } *) + +MODULE badimport2 ; + +FROM StrIO IMPORT Writestring ; + (* { dg-error "error: In program module 'badimport2': unknown symbol 'Writestring', did you mean WriteString?" "Writestring" { target *-*-* } 7 } *) + +BEGIN + +END badimport2. diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod new file mode 100644 index 0000000..ab82cd5 --- /dev/null +++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport3.mod @@ -0,0 +1,17 @@ + +(* { dg-do compile } *) +(* { dg-options "-g -c" } *) + +MODULE badimport3 ; + +CONST + Foo = 42 ; + +MODULE inner ; +IMPORT foo ; + (* { dg-error "error: In inner module 'inner': unknown symbol 'foo', did you mean Foo?" "foo" { target *-*-* } 11 } *) +END inner ; + + +BEGIN +END badimport3. diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod new file mode 100644 index 0000000..1b310d7 --- /dev/null +++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport4.mod @@ -0,0 +1,17 @@ + +(* { dg-do compile } *) +(* { dg-options "-g -c" } *) + +MODULE badimport4 ; + +CONST + Foo = 42 ; + +MODULE inner ; +IMPORT foo ; + (* { dg-error "error: In inner module 'inner': unknown symbol 'foo', did you mean Foo?" "foo" { target *-*-* } 11 } *) +END inner ; + + +BEGIN +END badimport4. diff --git a/gcc/testsuite/gnat.dg/vect19.adb b/gcc/testsuite/gnat.dg/vect19.adb new file mode 100644 index 0000000..af6f7e6 --- /dev/null +++ b/gcc/testsuite/gnat.dg/vect19.adb @@ -0,0 +1,17 @@ +-- { dg-do compile { target i?86-*-* x86_64-*-* } } +-- { dg-options "-O3 -msse2 -gnatn -fno-tree-slp-vectorize -fdump-tree-vect-details" } + +package body Vect19 is + + function NSum (X : Arr; N : Positive) return Arr is + Ret : Arr := X; + begin + for I in 1 .. N loop + Ret := Sum (Ret, X); + end loop; + return Ret; + end; + +end Vect19; + +-- { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } diff --git a/gcc/testsuite/gnat.dg/vect19.ads b/gcc/testsuite/gnat.dg/vect19.ads new file mode 100644 index 0000000..475f8d4 --- /dev/null +++ b/gcc/testsuite/gnat.dg/vect19.ads @@ -0,0 +1,7 @@ +with Vect19_Pkg; use Vect19_Pkg; + +package Vect19 is + + function NSum (X : Arr; N : Positive) return Arr; + +end Vect19; diff --git a/gcc/testsuite/gnat.dg/vect19_pkg.adb b/gcc/testsuite/gnat.dg/vect19_pkg.adb new file mode 100644 index 0000000..4c3b999 --- /dev/null +++ b/gcc/testsuite/gnat.dg/vect19_pkg.adb @@ -0,0 +1,12 @@ +package body Vect19_Pkg is + + function Sum (X : Arr; Y : Arr) return Arr is + Result : Arr; + begin + for I in X'Range loop + Result(I) := X(I) + Y(I); + end loop; + return Result; + end; + +end Vect19_Pkg; diff --git a/gcc/testsuite/gnat.dg/vect19_pkg.ads b/gcc/testsuite/gnat.dg/vect19_pkg.ads new file mode 100644 index 0000000..accd8af --- /dev/null +++ b/gcc/testsuite/gnat.dg/vect19_pkg.ads @@ -0,0 +1,9 @@ +package Vect19_Pkg is + + type Arr is array (1 .. 4) of Float; + for Arr'Alignment use 16; + + function Sum (X : Arr; Y : Arr) return Arr; + pragma Inline (Sum); + +end Vect19_Pkg; diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 50cdc2a..576a69c 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -7578,7 +7578,9 @@ vectorizable_reduction (loop_vec_info loop_vinfo, if ((double_reduc || neutral_op) && !nunits_out.is_constant () && (SLP_TREE_LANES (slp_node) != 1 && !reduc_chain) - && !operand_equal_p (neutral_op, vect_phi_initial_value (reduc_def_phi)) + && (!neutral_op + || !operand_equal_p (neutral_op, + vect_phi_initial_value (reduc_def_phi))) && !direct_internal_fn_supported_p (IFN_VEC_SHL_INSERT, vectype_out, OPTIMIZE_FOR_SPEED)) { diff --git a/libgomp/testsuite/libgomp.c/pr122281.c b/libgomp/testsuite/libgomp.c/pr122281.c new file mode 100644 index 0000000..68fc3be --- /dev/null +++ b/libgomp/testsuite/libgomp.c/pr122281.c @@ -0,0 +1,43 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O3" } */ + +/* PR libgomp/122281 */ +/* PR middle-end/105001 */ + +/* If SIMT is supported, the inner 'omp simd' is duplicated into + one SIMT and one SIMD variant. SIMT is currently only supported + with nvidia GPUs. (This only happens with -O1 or higher.) + + The duplication failed for the SIMD case as a tree was shared and + the initialization only happened in the SIMT branch, i.e. when + compiling for a SIMT-device, all non-SIMD (offload or host devices) + accesses failed (segfault) for the atomic update. */ + +#include <omp.h> + +int __attribute__((noinline, noclone)) +f(int *A, int n, int dev) { + int cnt = 0; + #pragma omp target map(cnt) map(to:A[0:n]) device(dev) + { + #pragma omp parallel for simd + for (int i = 0; i < n; i++) + if (A[i] != 0) + { + #pragma omp atomic + cnt++; + } + } + return cnt; +} + +int main() { + int n = 10; + int A[10] = {11,22,33,44,55,66,77,88,99,110}; + + /* Run over all devices, including the host; the host should be SIMD, + some non-host devices might be SIMT. */ + for (int dev = omp_initial_device; dev <= omp_get_num_devices(); dev++) + if (f (A, n, dev) != 10) + __builtin_abort(); +} diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e270c67..5d54d30 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,7 @@ +2025-11-02 Jason Merrill <jason@redhat.com> + + * src/c++23/std.cc.in: Uncomment usings for vprint_*_buffered. + 2025-10-30 Jakub Jelinek <jakub@redhat.com> * include/bits/version.def (is_implicit_lifetime): New. diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index b94b2cd..adc2982 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -56,7 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // as permitted (but not required) in the standard, in order to provide // better type safety in iostream calls. A side effect is that in C++98 // expressions involving them are not compile-time constants. - enum _Ios_Fmtflags + enum __attribute__((__flag_enum__)) _Ios_Fmtflags { _S_boolalpha = 1L << 0, _S_dec = 1L << 1, @@ -76,9 +76,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_adjustfield = _S_left | _S_right | _S_internal, _S_basefield = _S_dec | _S_oct | _S_hex, _S_floatfield = _S_scientific | _S_fixed, - _S_ios_fmtflags_end = 1L << 16, - _S_ios_fmtflags_max = __INT_MAX__, - _S_ios_fmtflags_min = ~__INT_MAX__ + _S_ios_fmtflags_end __attribute__((__unused__)) = 1L << 16, + _S_ios_fmtflags_max __attribute__((__unused__)) = __INT_MAX__, + _S_ios_fmtflags_min __attribute__((__unused__)) = ~__INT_MAX__ }; _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR @@ -176,15 +176,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __a = __a ^ __b; } - enum _Ios_Iostate + enum __attribute__((__flag_enum__)) _Ios_Iostate { _S_goodbit = 0, _S_badbit = 1L << 0, _S_eofbit = 1L << 1, _S_failbit = 1L << 2, - _S_ios_iostate_end = 1L << 16, - _S_ios_iostate_max = __INT_MAX__, - _S_ios_iostate_min = ~__INT_MAX__ + _S_ios_iostate_end __attribute__((__unused__)) = 1L << 16, + _S_ios_iostate_max __attribute__((__unused__)) = __INT_MAX__, + _S_ios_iostate_min __attribute__((__unused__)) = ~__INT_MAX__ }; _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR @@ -228,7 +228,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_beg = 0, _S_cur = _GLIBCXX_STDIO_SEEK_CUR, _S_end = _GLIBCXX_STDIO_SEEK_END, - _S_ios_seekdir_end = 1L << 16 + _S_ios_seekdir_end __attribute__((__unused__)) = 1L << 16 }; #if __cplusplus >= 201103L diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h index 636632a..54baed4 100644 --- a/libstdc++-v3/include/precompiled/stdc++.h +++ b/libstdc++-v3/include/precompiled/stdc++.h @@ -29,9 +29,7 @@ // 17.4.1.2 Headers // C -#ifndef _GLIBCXX_NO_ASSERT -#include <cassert> -#endif +// Don't include cassert, it's not suitable for PCH or header unit. #include <cctype> #include <cfloat> #include <climits> @@ -104,9 +102,6 @@ #if _GLIBCXX_HOSTED // C -#ifndef _GLIBCXX_NO_ASSERT -#include <cassert> -#endif #include <cctype> #include <cerrno> #include <cfloat> diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index 11a8d4f..27d83f1 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -23,11 +23,14 @@ module; +#include <bits/stdc++.h> + // stdc++.h doesn't include <execution> because of TBB issues; // FIXME for now let's avoid the problem by suppressing TBB. -#define _GLIBCXX_USE_TBB_PAR_BACKEND 0 - -#include <bits/stdc++.h> +#ifdef _PSTL_PAR_BACKEND_TBB +#undef _PSTL_PAR_BACKEND_TBB +#define _PSTL_PAR_BACKEND_SERIAL +#endif #include <execution> // Module std does include deprecated library interfaces. diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_assert_neg.cc b/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_assert_neg.cc index eb380c4..7ce90a2 100644 --- a/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_assert_neg.cc +++ b/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_assert_neg.cc @@ -1,8 +1,5 @@ // { dg-do compile } -// { dg-options "-D_GLIBCXX_NO_ASSERT" } // { dg-require-effective-target hosted } -// NB: This is done to force any generated and possibly included PCH -// to be invalid, and also to remove cassert from the include set. // 2005-05-24 bkoz diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/case_label.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/case_label.cc index c72e00f..6f0390b 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/case_label.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/case_label.cc @@ -68,12 +68,6 @@ case_labels(bitmask_type b) break; case std::ios_base::floatfield: break; - case std::_S_ios_fmtflags_end: - break; - case __INT_MAX__: - break; - case ~__INT_MAX__: - break; } using underlying_type = std::underlying_type<bitmask_type>::type; static_assert( sizeof(underlying_type) == sizeof(int), diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/case_label.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/case_label.cc index 6a1dd90..410f746 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/case_label.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/case_label.cc @@ -40,12 +40,6 @@ case_labels(bitmask_type b) break; case std::ios_base::failbit: break; - case std::_S_ios_iostate_end: - break; - case __INT_MAX__: - break; - case ~__INT_MAX__: - break; } using underlying_type = std::underlying_type<bitmask_type>::type; static_assert( sizeof(underlying_type) == sizeof(int), diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/case_label.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/case_label.cc index e132070..44b84a9 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/case_label.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/case_label.cc @@ -48,12 +48,6 @@ case_labels(bitmask_type b) case std::ios_base::noreplace: break; #endif - case std::_S_ios_openmode_end: - break; - case __INT_MAX__: - break; - case ~__INT_MAX__: - break; } using underlying_type = std::underlying_type<bitmask_type>::type; static_assert( sizeof(underlying_type) == sizeof(int), diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/seekdir/case_label.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/seekdir/case_label.cc index c7b9817..2dd1560 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/types/seekdir/case_label.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/types/seekdir/case_label.cc @@ -38,7 +38,5 @@ case_labels(test_type b) break; case std::ios_base::end: break; - case std::_S_ios_fmtflags_end: - break; } } diff --git a/libstdc++-v3/testsuite/util/exception/safety.h b/libstdc++-v3/testsuite/util/exception/safety.h index 8226c17..c62394c 100644 --- a/libstdc++-v3/testsuite/util/exception/safety.h +++ b/libstdc++-v3/testsuite/util/exception/safety.h @@ -24,6 +24,7 @@ #include <ext/throw_allocator.h> #include <cstdlib> // getenv, atoi #include <cstdio> // printf, fflush +#include <cassert> // assert // Container requirement testing. namespace __gnu_test |
