+2016-11-25 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-tailcall.c (find_tail_calls): Allow calls to reference
+ local variables if all references are known to be direct.
+
2016-11-25 Jakub Jelinek <jakub@redhat.com>
Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+2016-11-25 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/tree-ssa/tailcall-8.c: New test.
+
2016-11-25 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
* gcc.dg/pr64277.c: Use __INT32_TYPE__ for targets
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-tailc-details" } */
+
+struct s { int x; };
+void f_direct (struct s);
+void f_indirect (struct s *);
+void f_void (void);
+
+/* Tail call. */
+void
+g1 (struct s param)
+{
+ f_direct (param);
+}
+
+/* Tail call. */
+void
+g2 (struct s *param_ptr)
+{
+ f_direct (*param_ptr);
+}
+
+/* Tail call. */
+void
+g3 (struct s *param_ptr)
+{
+ f_indirect (param_ptr);
+}
+
+/* Tail call. */
+void
+g4 (struct s *param_ptr)
+{
+ f_indirect (param_ptr);
+ f_void ();
+}
+
+/* Tail call. */
+void
+g5 (struct s param)
+{
+ struct s local = param;
+ f_direct (local);
+}
+
+/* Tail call. */
+void
+g6 (struct s param)
+{
+ struct s local = param;
+ f_direct (local);
+ f_void ();
+}
+
+/* Not a tail call. */
+void
+g7 (struct s param)
+{
+ struct s local = param;
+ f_indirect (&local);
+}
+
+/* Not a tail call. */
+void
+g8 (struct s *param_ptr)
+{
+ struct s local = *param_ptr;
+ f_indirect (&local);
+}
+
+/* Not a tail call. */
+void
+g9 (struct s *param_ptr)
+{
+ struct s local = *param_ptr;
+ f_indirect (&local);
+ f_void ();
+}
+
+/* { dg-final { scan-tree-dump-times "Found tail call" 6 "tailc" } } */
tail_recursion = true;
}
- /* Make sure the tail invocation of this function does not refer
- to local variables. */
+ /* Make sure the tail invocation of this function does not indirectly
+ refer to local variables. (Passing variables directly by value
+ is OK.) */
FOR_EACH_LOCAL_DECL (cfun, idx, var)
{
if (TREE_CODE (var) != PARM_DECL
&& auto_var_in_fn_p (var, cfun->decl)
+ && may_be_aliased (var)
&& (ref_maybe_used_by_stmt_p (call, var)
|| call_may_clobber_ref_p (call, var)))
return;