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  <mjam...@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  <mjam...@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 --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"  } } */
-- 
2.43.0

Reply via email to