This is a regression present on the mainline and 4.9 branch (at least): the 
recently added tree-ssa-tail-merge.c pass totally disregards the static chain 
of calls, so it can wrongly merge 2 calls to the same function with different 
instances of a non-local frame object generated by inlining.

Tested on x86_64-suse-linux, applied on mainline and 4.9 branch as obvious.


2014-06-07  Eric Botcazou  <ebotca...@adacore.com>

        * tree-ssa-tail-merge.c (same_succ_hash): Hash the static chain of a
        call statement, if any.
        (gimple_equal_p) <GIMPLE_CALL>: Compare the static chain of the call
        statements, if any.  Tidy up.


2014-06-07  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/opt38.adb: New test.
        * gnat.dg/opt38_pkg.ad[sb]: New helper.


-- 
Eric Botcazou
Index: tree-ssa-tail-merge.c
===================================================================
--- tree-ssa-tail-merge.c	(revision 211313)
+++ tree-ssa-tail-merge.c	(working copy)
@@ -481,7 +481,11 @@ same_succ_hash (const_same_succ e)
 	hashval = iterative_hash_hashval_t
 	  ((hashval_t) gimple_call_internal_fn (stmt), hashval);
       else
-	hashval = iterative_hash_expr (gimple_call_fn (stmt), hashval);
+	{
+	  hashval = iterative_hash_expr (gimple_call_fn (stmt), hashval);
+	  if (gimple_call_chain (stmt))
+	    hashval = iterative_hash_expr (gimple_call_chain (stmt), hashval);
+	}
       for (i = 0; i < gimple_call_num_args (stmt); i++)
 	{
 	  arg = gimple_call_arg (stmt, i);
@@ -1121,18 +1125,23 @@ gimple_equal_p (same_succ same_succ, gim
   switch (gimple_code (s1))
     {
     case GIMPLE_CALL:
-      if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
-	return false;
       if (!gimple_call_same_target_p (s1, s2))
         return false;
 
+      t1 = gimple_call_chain (s1);
+      t2 = gimple_call_chain (s2);
+      if (!gimple_operand_equal_value_p (t1, t2))
+	return false;
+
+      if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
+	return false;
+
       for (i = 0; i < gimple_call_num_args (s1); ++i)
 	{
 	  t1 = gimple_call_arg (s1, i);
 	  t2 = gimple_call_arg (s2, i);
-	  if (gimple_operand_equal_value_p (t1, t2))
-	    continue;
-	  return false;
+	  if (!gimple_operand_equal_value_p (t1, t2))
+	    return false;
 	}
 
       lhs1 = gimple_get_lhs (s1);
-- { dg-do run }
-- { dg-options "-O2 -gnatn" }

with Opt38_Pkg; use Opt38_Pkg;

procedure Opt38 is
begin
  Test (-1);
end;
package body Opt38_Pkg is

  procedure Proc (I : Integer);
  pragma Inline (Proc);

  procedure Proc (I : Integer) is

    procedure Inner;
    pragma No_Inline (Inner);

    procedure Inner is
    begin
      if I /= 110 then
        raise Program_Error;
      end if;
    end;

  begin
    if I > 0 then
      Inner;
    end if;
  end;

  procedure Test (I : Integer) is
  begin
    if I > -1 then
      Proc (I);
    else
      Proc (I + 111);
    end if;
  end;

end Opt38_Pkg;
package Opt38_Pkg is

  procedure Test (I : Integer);

end Opt38_Pkg;

Reply via email to