Richard already approved this, but FWIW also looks goods to me.  Except I can't
say anything about the testcases, since I don't know Ada at all :).

Thanks for the patch,
Filip Kastl

On Wed 2026-07-01 09:47:46, Eric Botcazou wrote:
> Hi,
> 
> this is a regression present on mainline, 16, 15 and 14 branches introduced 
> by 
> the fix for PR tree-optimization/112653 (PTA and return).  What happens is 
> that DSE incorrectly eliminates a call to __builtin_memcpy, whose destination 
> is obtained from (an equivalent of) malloc and is ultimately returned from 
> the 
> function.  But this happens only when the dynamic allocation is conditional.
> 
> The difference between the unconditional and conditional cases is:
> 
> ESCAPED_RETURN = { ESCAPED NONLOCAL HEAP(30) }
> 
> vs
> 
> ESCAPED_RETURN = { ANYTHING }
> 
> The proposed fix is to apply in set_uids_in_ptset the same treatment to 
> ANYTHING in the escaped return case as in the escaped case.
> 
> Tested on x86-64/Linux, OK for all affected branches?
> 
> 
> 2026-07-01  Eric Botcazou  <[email protected]>
> 
>       * tree-ssa-structalias.cc (set_uids_in_ptset): If ANYTHING is
>       present in the ESCAPED_RETURN solution, record that the global
>       solution has an escaped heap if FROM contains a heap variable.
> 
> 
> 2026-07-01  Eric Botcazou  <[email protected]>
> 
>       * gnat.dg/opt109.adb: New test.
>       * gnat.dg/opt109_pkg.ads, gnat.dg/opt109_pkg.adb: New helper.
> 
> -- 
> Eric Botcazou

> diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc
> index ab6658a0981..8a22d6b3ce9 100644
> --- a/gcc/tree-ssa-structalias.cc
> +++ b/gcc/tree-ssa-structalias.cc
> @@ -745,12 +745,15 @@ static void
>  set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt,
>                  tree fndecl)
>  {
> +  const varinfo_t escaped_vi = get_varinfo (var_rep[escaped_id]);
> +  const varinfo_t escaped_return_vi = get_varinfo 
> (var_rep[escaped_return_id]);
> +  const bool everything_escaped
> +    = escaped_vi->solution && bitmap_bit_p (escaped_vi->solution, 
> anything_id);
> +  const bool everything_escaped_return
> +    = escaped_return_vi->solution
> +      && bitmap_bit_p (escaped_return_vi->solution, anything_id);
>    unsigned int i;
>    bitmap_iterator bi;
> -  varinfo_t escaped_vi = get_varinfo (var_rep[escaped_id]);
> -  varinfo_t escaped_return_vi = get_varinfo (var_rep[escaped_return_id]);
> -  bool everything_escaped
> -    = escaped_vi->solution && bitmap_bit_p (escaped_vi->solution, 
> anything_id);
>  
>    EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
>      {
> @@ -766,8 +769,10 @@ set_uids_in_ptset (bitmap into, bitmap from, struct 
> pt_solution *pt,
>         pt->vars_contains_escaped = true;
>         pt->vars_contains_escaped_heap |= vi->is_heap_var;
>       }
> -      if (escaped_return_vi->solution
> -       && bitmap_bit_p (escaped_return_vi->solution, i))
> +
> +      if (everything_escaped_return
> +       || (escaped_return_vi->solution
> +           && bitmap_bit_p (escaped_return_vi->solution, i)))
>       pt->vars_contains_escaped_heap |= vi->is_heap_var;
>  
>        if (vi->is_restrict_var)

> -- { dg-do run }
> -- { dg-options "-O" }
> 
> with Opt109_Pkg; use Opt109_Pkg;
> 
> procedure Opt109 is
>   S : constant String := "Hello World!";
>   R : constant Rec := F (S);
> begin
>   if R.B.Data.all /= S then
>     raise Program_Error;
>   end if;
> end;

> package body Opt109_Pkg is
> 
>    function F (Value : String) return Rec is
>    begin
>       if Value'Length > Max then
>          return Result : Rec (Is_Small => False) do
>             Result.B.Data := new String'(Value);
>          end return;
>       else
>          return Result : Rec (Is_Small => True) do
>             Result.S.Data (Value'Length + 1 .. Max) := (others => ' ');
>          end return;
>       end if;
>    end;
> 
> end Opt109_Pkg;

> with System;
> 
> package Opt109_Pkg is
> 
>    Max : constant Natural := 7;
>    subtype Small_String_Size is Natural range 0 .. Max;
> 
>    type Small_String is record
>       Is_Small : Boolean;
>       Length   : Small_String_Size;
>       Data     : aliased String (1 .. Max);
>    end record;
> 
>    type Big_String_Access is access all String;
> 
>    type Big_String is record
>       Data : Big_String_Access := null;
>    end record;
> 
>    for Big_String use record
>       Data at 0 range 0 .. System.Word_Size - 1;
>    end record;
> 
>    type Rec (Is_Small : Boolean := True) is record
>       case Is_Small is
>          when True  => S : Small_String;
>          when False => B : Big_String;
>       end case;
>    end record with Unchecked_Union;
> 
>    function F (Value : String) return Rec;
> 
> end Opt109_Pkg;

Reply via email to