This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: TREE_UNCHANGING?
- From: Jason Merrill <jason at redhat dot com>
- To: gcc at gcc dot gnu dot org
- Cc: Jason Merrill <jason at redhat dot com>
- Date: Thu, 09 May 2002 02:10:18 +0100
- Subject: Re: TREE_UNCHANGING?
- References: <wvld6w6x0go.fsf@prospero.cambridge.redhat.com>
>>>>> "Jason" == Jason Merrill <jason@redhat.com> writes:
> I would like to be able to tell the backend that the vtable for a class
> object will never change, regardless of anything else we might or might not
> know about that object, so we can hoist vtable lookups out of loops.
Tangent:
While setting TREE_CONSTANT does the trick for normal virtual function
calls, it isn't enough for calls through a pointer-to-member function.
This turns out to be because the loop optimizer isn't clever enough to
hoist the complicated code for resolving a pmf, which involves a test and
jump.
I've whipped up a C analog below; this testcase takes 50% longer to run
with -O2 than with -O2 -fno-inline, because of the const function
optimization. If we inline, we lose that information; there ought to be a
way to express the same thing for inlined/open-coded routines.
I thought about using a libcall block, but that seems to be specific to
calls. Any reason not to use it for an arbitrary block of code with
defined inputs and output? <hack, hack> Nope, doesn't work. loop still
looks at the individual insns, and doesn't think it can move some of the
internal sets.
Does the AST optimizer branch support anything like this?
typedef void (*pfn_type)();
typedef struct PMF {
union {
pfn_type pfn;
int idx;
} u;
// ignored for this example
int delta;
} PMF;
typedef struct A {
pfn_type* vptr;
} A;
static inline pfn_type extract_pfn (A* ap, PMF pmf) __attribute__ ((const));
static inline pfn_type extract_pfn (A* ap, PMF pmf)
{
if (pmf.u.idx & 1)
{
// virtual; get the pointer from the vtable.
int idx = pmf.u.idx - 1;
void *pos = ((void *)ap->vptr) + idx;
return *(pfn_type *)pos;
}
else
// non-virtual
return pmf.u.pfn;
}
void f (A* ap, PMF pmf)
{
int i;
for (i = 0; i < 500000000; ++i)
{
extract_pfn (ap, pmf) ();
}
}
void g() {}
pfn_type vtable[] = { g };
int main()
{
A a = { vtable };
PMF pmf_nonv = { g, 0 };
PMF pmf_virt = { (pfn_type)1, 0 };
f (&a, pmf_nonv);
f (&a, pmf_virt);
}