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