> Hi,
>
> On Mon, Feb 03, 2014 at 12:52:49AM +0100, Jan Hubicka wrote:
> > Hi,
> > this patch fixes the bug in extr_type_from_vtbl_ptr_store that made it to
> > consider store of construction virtual table or virtual table of virtual
> > base
> > as store of type's virtual table.
> >
> > In the testcase we have after early inlining:
> > virtual C::~C() (struct C * const this)
> > {
> > unsigned int i;
> > struct MultiTermDocs * _4;
> > struct A * _7;
> > unsigned int _10;
> >
> > <bb 2>:
> > this_2(D)->D.2980._vptr.MultiTermDocs = &MEM[(void *)&_ZTV1C + 24B];
> > _4 = &this_2(D)->D.2980;
> > MEM[(struct MultiTermDocs *)this_2(D)]._vptr.MultiTermDocs = &MEM[(void
> > *)&_ZTC1C0_13MultiTermDocs + 24B];
> > MultiTermDocs::wrap (_4);
> >
> > &_ZTC1C0_13MultiTermDocs is the construction vtable, while its context is
> > structure C and we thus assume that it is initialized to &_ZTV1C + 16B in
> > the
> > rest of code.
> >
> > This leads to wrong jump function:
> > Jump functions of caller virtual C::~C()/29:
> > callsite virtual C::~C()/29 -> MultiTermDocs::~MultiTermDocs()/10 :
> > param 0: KNOWN TYPE: base struct C, offset 0, component struct
> > MultiTermDocs
> > param 1: CONST: &MEM[(void *)&_ZTT1C + 8B]
> >
> > This is wrong, since type of _4 at call of WRAP is really construction of C.
> > With the patch we get:
> >
> > Jump functions of caller virtual C::~C()/29:
> > callsite virtual C::~C()/29 -> void MultiTermDocs::wrap()/8 :
>
> This jump function describes a different call than the one above, I
> assume the problem was that we had KNOWN_TYPE here too.
Yes, sorry, seems I copied dumps from different compilation.
The jump function from mainline before patch on testcase atteched is:
Jump functions of caller virtual C::~C()/29:
callsite virtual C::~C()/29 -> void MultiTermDocs::wrap()/8 :
param 0: KNOWN TYPE: base struct C, offset 0, component struct
MultiTermDocs
>
> > param 0: ANCESTOR: 0, offset 0, struct MultiTermDocs
> >
> > It looks bit confusing, but the ANCESTOR has no type_preserved flag,
>
> ANCESTOR jump functions certainly have type_preserved flag and as long
> as they are created with ipa_set_ancestor_jf it is impossible to
Breakpoint 5, ipa_set_ancestor_jf (jfunc=0x7ffff69050b0, offset=0,
type=0x7ffff6cd2f18, formal_id=0, agg_preserved=false, type_preserved=false) at
../../gcc/ipa-prop.c:480
480 jfunc->type = IPA_JF_ANCESTOR;
(gdb) bt
#0 ipa_set_ancestor_jf (jfunc=0x7ffff69050b0, offset=0, type=0x7ffff6cd2f18,
formal_id=0, agg_preserved=false, type_preserved=false) at
../../gcc/ipa-prop.c:480
#1 0x0000000000b6f89f in compute_complex_assign_jump_func (info=0x1f0af58,
parms_ainfo=0x7fffffffe640, jfunc=0x7ffff69050b0, call=0x7ffff6923098,
stmt=0x7ffff68f3c30, name=0x7ffff6921000,
param_type=0x7ffff6cd52a0) at ../../gcc/ipa-prop.c:1108
#2 0x0000000000b714a1 in ipa_compute_jump_functions_for_edge
(parms_ainfo=0x7fffffffe640, cs=0x7ffff6904750) at ../../gcc/ipa-prop.c:1650
#3 0x0000000000b71742 in ipa_compute_jump_functions (node=0x7ffff68efe18,
parms_ainfo=0x7fffffffe640) at ../../gcc/ipa-prop.c:1699
#4 0x0000000000b72f42 in ipa_analyze_node (node=0x7ffff68efe18) at
../../gcc/ipa-prop.c:2236
(gdb) up
#1 0x0000000000b6f89f in compute_complex_assign_jump_func (info=0x1f0af58,
parms_ainfo=0x7fffffffe640, jfunc=0x7ffff69050b0, call=0x7ffff6923098,
stmt=0x7ffff68f3c30, name=0x7ffff6921000,
param_type=0x7ffff6cd52a0) at ../../gcc/ipa-prop.c:1108
1108 call, ssa),
type_p);
(gdb) l
1103 bool type_p = !detect_type_change (op1, base, TREE_TYPE
(param_type),
1104 call, jfunc, offset);
1105 if (type_p || jfunc->type == IPA_JF_UNKNOWN)
1106 ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (op1), index,
1107 parm_ref_data_pass_through_p
(&parms_ainfo[index],
1108 call, ssa),
type_p);
so here we have type_p false but we still make ancestor jf - that is correct
(kind of): we really call destructor on ancestor and we change the dynamic type
(by storing construction vtable) before it.
> forget to set/clear it. I have even verified we update and honor the
> flag during inlining.
>
> > so it is basically just PASS_THROUGH in a funny representation.
>
> Well, I have always known we produce ancestors with zero offset given
> exactly this kind of input but I have never seen any real need to
> convert them to simple pass-throughs.
Yep, no problem with that - just made me bit confused as I originaly read
ANCESTOR in a sense of implicit TYPE_PRESERVED flag :)
Honza
>
> Anyway, the ipa-prop.c part is of course fine assuming that
> ipa-devirt.c parts work :-) But I'm too tired to attempt to understand
> it now and will probably need to read the whole file again anyway
> because I rememer little and am getting increasingly lost in this
> discussion.
>
> Thanks,
>
> Martin