diff mbox series

ipa: Create indirect call edges also for lambdas

Message ID ri6y1bdx3yg.fsf@virgil.suse.cz
State New
Headers show
Series ipa: Create indirect call edges also for lambdas | expand

Commit Message

Martin Jambor Feb. 21, 2024, 2:54 p.m. UTC
Hi,

Even though we have had code to handle creation of indirect call graph
edges (so that these calls can than be made direct as part of IPA-CP
and inlining and eventually also inlined) for C++ member pointers for
many years, this code expects the member pointers to be structures
passed by value.  In PR 108802 it turned out that for lambdas these
are passed by reference.  This patch adjusts the code for that so that
small lambdas are also inlineable without depending on early inlining.

Bootstrapped and LTO bootstrapped on x86_64-linux.  This is technically
a regression against GCC 10.  OK for master even now?

Thanks,

Martin


gcc/ChangeLog:

2024-02-20  Martin Jambor  <mjambor@suse.cz>

	PR ipa/108802
	* ipa-prop.cc (ipa_get_stmt_member_ptr_load_param): Also recognize
	loads from a pointer parameter.
	(ipa_analyze_indirect_call_uses): Likewise.

gcc/testsuite/ChangeLog:

2024-02-20  Martin Jambor  <mjambor@suse.cz>

	PR ipa/108802
	* g++.dg/ipa/pr108802.C: New test.
---
 gcc/ipa-prop.cc                     | 56 +++++++++++++++++++++--------
 gcc/testsuite/g++.dg/ipa/pr108802.C | 14 ++++++++
 2 files changed, 55 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ipa/pr108802.C
diff mbox series

Patch

diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index bec0ebd210c..25d252fd57c 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -2514,14 +2514,26 @@  ipa_get_stmt_member_ptr_load_param (gimple *stmt, bool use_delta,
   if (TREE_CODE (rhs) != MEM_REF)
     return NULL_TREE;
   rec = TREE_OPERAND (rhs, 0);
-  if (TREE_CODE (rec) != ADDR_EXPR)
-    return NULL_TREE;
-  rec = TREE_OPERAND (rec, 0);
-  if (TREE_CODE (rec) != PARM_DECL
-      || !type_like_member_ptr_p (TREE_TYPE (rec), &ptr_field, &delta_field))
+  if (TREE_CODE (rec) == ADDR_EXPR)
+    {
+      rec = TREE_OPERAND (rec, 0);
+      if (TREE_CODE (rec) != PARM_DECL
+	  || !type_like_member_ptr_p (TREE_TYPE (rec), &ptr_field,
+				      &delta_field))
+	return NULL_TREE;
+    }
+  else if (TREE_CODE (rec) == SSA_NAME
+	   && SSA_NAME_IS_DEFAULT_DEF (rec))
+    {
+      if (TREE_CODE (SSA_NAME_VAR (rec)) != PARM_DECL
+	  || !type_like_member_ptr_p (TREE_TYPE (TREE_TYPE (rec)), &ptr_field,
+				      &delta_field))
+	return NULL_TREE;
+    }
+  else
     return NULL_TREE;
-  ref_offset = TREE_OPERAND (rhs, 1);
 
+  ref_offset = TREE_OPERAND (rhs, 1);
   if (use_delta)
     fld = delta_field;
   else
@@ -2757,17 +2769,31 @@  ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call,
   if (rec != rec2)
     return;
 
-  index = ipa_get_param_decl_index (info, rec);
-  if (index >= 0
-      && parm_preserved_before_stmt_p (fbi, index, call, rec))
+  if (TREE_CODE (rec) == SSA_NAME)
     {
-      struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
-	 					    call, false);
-      cs->indirect_info->offset = offset;
-      cs->indirect_info->agg_contents = 1;
-      cs->indirect_info->member_ptr = 1;
-      cs->indirect_info->guaranteed_unmodified = 1;
+      index = ipa_get_param_decl_index (info, SSA_NAME_VAR (rec));
+      if (index < 0
+	  || !parm_ref_data_preserved_p (fbi, index, call,
+					 gimple_assign_rhs1 (def)))
+	return;
+      by_ref = true;
     }
+  else
+    {
+      index = ipa_get_param_decl_index (info, rec);
+      if (index < 0
+	  || !parm_preserved_before_stmt_p (fbi, index, call, rec))
+	return;
+      by_ref = false;
+    }
+
+  struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index,
+						call, false);
+  cs->indirect_info->offset = offset;
+  cs->indirect_info->agg_contents = 1;
+  cs->indirect_info->member_ptr = 1;
+  cs->indirect_info->by_ref = by_ref;
+  cs->indirect_info->guaranteed_unmodified = 1;
 
   return;
 }
diff --git a/gcc/testsuite/g++.dg/ipa/pr108802.C b/gcc/testsuite/g++.dg/ipa/pr108802.C
new file mode 100644
index 00000000000..2e2b6c66b64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr108802.C
@@ -0,0 +1,14 @@ 
+/* { dg-do compile  } */
+/* { dg-options "-O2 -std=c++14 -fdump-ipa-inline -fno-early-inlining"  } */
+/* { dg-add-options bind_pic_locally } */
+
+struct A {
+    int interesting(int x) { return 2 * x; }
+};
+
+int f1() {
+    A a;
+    return [&](auto&& f) { return (a.*f)(42); } (&A::interesting);
+}
+
+/* { dg-final { scan-ipa-dump "A::interesting\[^\\n\]*inline copy in int f1"  "inline"  } } */