This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: improve expansion of C++ pointer to member function constants
- From: "Ollie Wild" <aaw at google dot com>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 14 Nov 2007 22:29:31 -0800
- Subject: PATCH: improve expansion of C++ pointer to member function constants
When expanding a pointer to member function constant, the C++ front
end fails to extract the delta field, generating instead a
COMPONENT_REF of unknown value. This interferes with folding, and can
result in failed optimizations.
For example, consider the following code fragment:
struct S {
void f () {};
};
template<void (S::*pf) ()> void g(S &s)
{
(s.*pf) (); // s.f ()
}
void h ()
{
S s;
g<&S::f> (s);
}
Replacing (s.*pf) () with s.f (), should generate identical code.
However, with -O0 on x86, the code as is generates a block like:
movl $_ZN1S1fEv, %eax
movl $0, %edx
movl %edx, %eax
addl 8(%ebp), %eax
movl %eax, (%esp)
call _ZN1S1fEv
The assembly with s.f () is the much simpler:
movl 8(%ebp), %eax
movl %eax, (%esp)
call _ZN1S1fEv
Things get even worse when optimization is enabled. With -O2, the
calls are all inlined. However, in the first case, the definition of
_ZN1S1fEv is not removed, resulting in excess code generation.
This patch resolves the problem by adding a delta_from_ptrmemfunc
function which mirrors the behavior of the existing
pfn_from_ptrmemfunc function. With this improvement, the code
generated by the two examples is identical.
Tested with a C/C++/Java bootstrap and testsuite on i686-pc-linux-gnu.
Ollie
:ADDPATCH c++:
2007-11-14 Ollie Wild <aaw@google.com>
* typeck.c (delta_from_ptrmemfunc): New function.
(get_member_function_from_ptrfunc): Call delta_from_ptrmemfunc.
(build_binary_op): Call delta_from_ptrmemfunc.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d167de2..da46bb3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
static tree pfn_from_ptrmemfunc (tree);
+static tree delta_from_ptrmemfunc (tree);
static tree convert_for_assignment (tree, tree, const char *, tree, int);
static tree cp_pointer_int_sum (enum tree_code, tree, tree);
static tree rationalize_conditional_expr (enum tree_code, tree);
@@ -2586,7 +2587,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* Start by extracting all the information from the PMF itself. */
e3 = pfn_from_ptrmemfunc (function);
- delta = build_ptrmemfunc_access_expr (function, delta_identifier);
+ delta = delta_from_ptrmemfunc (function);
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
@@ -3370,8 +3371,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
== ptrmemfunc_vbit_in_delta)
{
tree pfn0 = pfn_from_ptrmemfunc (op0);
- tree delta0 = build_ptrmemfunc_access_expr (op0,
- delta_identifier);
+ tree delta0 = delta_from_ptrmemfunc (op0);
tree e1 = cp_build_binary_op (EQ_EXPR,
pfn0,
fold_convert (TREE_TYPE (pfn0),
@@ -3412,10 +3412,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
pfn0 = pfn_from_ptrmemfunc (op0);
pfn1 = pfn_from_ptrmemfunc (op1);
- delta0 = build_ptrmemfunc_access_expr (op0,
- delta_identifier);
- delta1 = build_ptrmemfunc_access_expr (op1,
- delta_identifier);
+ delta0 = delta_from_ptrmemfunc (op0);
+ delta1 = delta_from_ptrmemfunc (op1);
if (TARGET_PTRMEMFUNC_VBIT_LOCATION
== ptrmemfunc_vbit_in_delta)
{
@@ -6290,6 +6288,25 @@ pfn_from_ptrmemfunc (tree t)
return build_ptrmemfunc_access_expr (t, pfn_identifier);
}
+/* Return an expression for DELTA from the pointer-to-member function
+ given by T. */
+
+static tree
+delta_from_ptrmemfunc (tree t)
+{
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree delta;
+ tree pfn;
+
+ expand_ptrmemfunc_cst (t, &delta, &pfn);
+ if (delta)
+ return delta;
+ }
+
+ return build_ptrmemfunc_access_expr (t, delta_identifier);
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. ERRTYPE is a string to use in error
messages: "assignment", "return", etc. If FNDECL is non-NULL, we