===================================================================
@@ -781,10 +781,11 @@ get_ssa_def_if_simple_copy (tree rhs)
}
/* Traverse statements from CALL backwards, scanning whether the argument ARG
- which is a member pointer is filled in with constant values. If it is, fill
- the jump function JFUNC in appropriately. METHOD_FIELD and DELTA_FIELD are
- fields of the record type of the member pointer. To give an example, we
- look for a pattern looking like the following:
+ which is a member pointer and is not addressable is filled in with constant
+ values. If it is, fill the jump function JFUNC in appropriately.
+ METHOD_FIELD and DELTA_FIELD are fields of the record type of the member
+ pointer. To give an example, we look for a pattern looking like the
+ following:
D.2515.__pfn ={v} printStuff;
D.2515.__delta ={v} 0;
@@ -806,6 +807,8 @@ determine_cst_member_ptr (gimple call, t
gimple stmt = gsi_stmt (gsi);
tree lhs, rhs, fld;
+ if (!stmt_may_clobber_ref_p (stmt, arg))
+ continue;
if (!gimple_assign_single_p (stmt))
return;
@@ -814,7 +817,7 @@ determine_cst_member_ptr (gimple call, t
if (TREE_CODE (lhs) != COMPONENT_REF
|| TREE_OPERAND (lhs, 0) != arg)
- continue;
+ return;
fld = TREE_OPERAND (lhs, 1);
if (!method && fld == method_field)
@@ -1030,6 +1033,10 @@ ipa_note_param_call (struct cgraph_node
<bb 2>:
f$__delta_5 = f.__delta;
f$__pfn_24 = f.__pfn;
+
+ ...
+
+ <bb 5>
D.2496_3 = (int) f$__pfn_24;
D.2497_4 = D.2496_3 & 1;
if (D.2497_4 != 0)
@@ -1037,7 +1044,7 @@ ipa_note_param_call (struct cgraph_node
else
goto <bb 4>;
- <bb 3>:
+ <bb 6>:
D.2500_7 = (unsigned int) f$__delta_5;
D.2501_8 = &S + D.2500_7;
D.2502_9 = (int (*__vtbl_ptr_type) (void) * *) D.2501_8;
@@ -1048,7 +1055,7 @@ ipa_note_param_call (struct cgraph_node
D.2507_15 = *D.2506_14;
iftmp.11_16 = (String:: *) D.2507_15;
- <bb 4>:
+ <bb 7>:
# iftmp.11_1 = PHI <iftmp.11_16(3), f$__pfn_24(2)>
D.2500_19 = (unsigned int) f$__delta_5;
D.2508_20 = &S + D.2500_19;
@@ -1109,17 +1116,18 @@ ipa_analyze_indirect_call_uses (struct c
d1 = SSA_NAME_DEF_STMT (n1);
d2 = SSA_NAME_DEF_STMT (n2);
+ join = gimple_bb (def);
if ((rec = ipa_get_stmt_member_ptr_load_param (d1, false)))
{
if (ipa_get_stmt_member_ptr_load_param (d2, false))
return;
- bb = gimple_bb (d1);
+ bb = EDGE_PRED (join, 0)->src;
virt_bb = gimple_bb (d2);
}
else if ((rec = ipa_get_stmt_member_ptr_load_param (d2, false)))
{
- bb = gimple_bb (d2);
+ bb = EDGE_PRED (join, 1)->src;
virt_bb = gimple_bb (d1);
}
else
@@ -1128,7 +1136,6 @@ ipa_analyze_indirect_call_uses (struct c
/* Second, we need to check that the basic blocks are laid out in the way
corresponding to the pattern. */
- join = gimple_bb (def);
if (!single_pred_p (virt_bb) || !single_succ_p (virt_bb)
|| single_pred (virt_bb) != bb
|| single_succ (virt_bb) != join)
@@ -1138,7 +1145,7 @@ ipa_analyze_indirect_call_uses (struct c
significant bit of the pfn. */
branch = last_stmt (bb);
- if (gimple_code (branch) != GIMPLE_COND)
+ if (!bb || gimple_code (branch) != GIMPLE_COND)
return;
if (gimple_cond_code (branch) != NE_EXPR
===================================================================
@@ -0,0 +1,61 @@
+/* Verify that simple indirect calls are inlined even without early
+ inlining.. */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining" } */
+/* { dg-add-options bind_pic_locally } */
+
+extern void non_existent (const char *, int);
+
+class String
+{
+private:
+ const char *data;
+
+public:
+ String (const char *d) : data(d)
+ {}
+
+ int funcOne (int delim) const;
+ int printStuffTwice (int delim) const;
+};
+
+
+int String::funcOne (int delim) const
+{
+ int i;
+ for (i = 0; i < delim; i++)
+ non_existent(data, i);
+
+ return 1;
+}
+
+extern int global;
+
+int docalling (int c, int (String::* f)(int delim) const)
+{
+ String S ("muhehehe");
+
+ if (c > 2)
+ global = 3;
+ else
+ global = 5;
+
+ return (S.*f)(4);
+}
+
+int __attribute__ ((noinline,noclone)) get_input (void)
+{
+ return 1;
+}
+
+int main (int argc, char *argv[])
+{
+ int i = 0;
+ while (i < 1000)
+ i += docalling (get_input (), &String::funcOne);
+ non_existent ("done", i);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump "String::funcOne\[^\\n\]*inline copy in int main" "inline" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */