------- Comment #2 from rguenther at suse dot de 2010-09-09 08:43 ------- Subject: Re: New: Missed devirtualization
On Thu, 9 Sep 2010, hubicka at gcc dot gnu dot org wrote: > The following testcase taken from testsuite (and many others): > // PR 14535 > // { dg-do run } > // { dg-options "-O -finline" } > // > // Original test case failure required that Raiser constructor be inlined. > > extern "C" void abort(); > bool destructor_called = false; > > struct B { > virtual void Run(){}; > }; > > struct D : public B { > virtual void Run() > { > struct O { > ~O() { destructor_called = true; }; > } o; > > struct Raiser { > Raiser() throw( int ) {throw 1;}; > } raiser; > }; > }; > > int main() { > try { > D d; > static_cast<B&>(d).Run(); > } catch (...) {} > > if (!destructor_called) > abort (); > } > > leads to following in .optimized dump: > <bb 2>: > MEM[(struct B *)&d]._vptr.B = &_ZTV1B[2]; > d.D.2108._vptr.B = &_ZTV1D[2]; > D.2210_2 = _ZTV1D[2]; > OBJ_TYPE_REF(D.2210_2;&d.D.2108->0) (&d.D.2108); > > Obviously OBJ_TYPE_REF can be optimized here since we know the > virtual table. Why it is missed? > > I run into it because my new folding code is actually smart enough to lead to: > int (*__vtbl_ptr_type) (void) > > void D::<T400> (struct D *) > > D.2210_2 = Run; > > The error comes because we pick from initializer of VTBL the following > ADDR_EXPR: > <addr_expr 0x7ffff7ec8b10 > type <pointer_type 0x7ffff6b7db28 __vtbl_ptr_type > type <function_type 0x7ffff6b7da80 type <integer_type 0x7ffff7edb498 > int> > type_6 QI > size <integer_cst 0x7ffff7ec54d8 constant 8> > unit size <integer_cst 0x7ffff7ec5500 constant 1> > align 8 symtab 0 alias set -1 canonical type 0x7ffff6b7da80 > pointer_to_this <pointer_type 0x7ffff6b7db28 __vtbl_ptr_type>> > unsigned type_6 DI > size <integer_cst 0x7ffff7ec57d0 constant 64> > unit size <integer_cst 0x7ffff7ec57f8 constant 8> > align 64 symtab 0 alias set -1 canonical type 0x7ffff6b7db28 > pointer_to_this <pointer_type 0x7ffff6b7dc78>> > constant > arg 0 <function_decl 0x7ffff6b8e500 Run > type <method_type 0x7ffff6b9b9d8 type <void_type 0x7ffff7edbe70 void> > type_6 QI size <integer_cst 0x7ffff7ec54d8 8> unit size > <integer_cst 0x7ffff7ec5500 1> > align 8 symtab 0 alias set -1 canonical type 0x7ffff6b9b9d8 method > basetype <record_type 0x7ffff6b9b7e0 D> > arg-types <tree_list 0x7ffff6b80af0 value <pointer_type > 0x7ffff6b9ba80> > chain <tree_list 0x7ffff7eed398 value <void_type > 0x7ffff7edbe70 > void>>> > pointer_to_this <pointer_type 0x7ffff6bab150>> > addressable volatile asm_written used public static weak autoinline > virtual decl_5 QI file /home/jh/a.C line 15 col 18 align 16 context > <record_type 0x7ffff6b9b7e0 D> initial <error_mark 0x7ffff7ecdb28> > arguments <parm_decl 0x7ffff7ece990 this type <pointer_type > 0x7ffff6b9bb28> > readonly unsigned DI file /home/jh/a.C line 15 col 22 size > <integer_cst 0x7ffff7ec57d0 64> unit size <integer_cst 0x7ffff7ec57f8 8> > align 64 context <function_decl 0x7ffff6b8e500 Run> > (reg/f:DI 62 [ this ]) arg-type <pointer_type 0x7ffff6b9bb28> > incoming-rtl (reg:DI 5 di [ this ])> > result <result_decl 0x7ffff7ed0380 D.2112 type <void_type > 0x7ffff7edbe70 void> > ignored VOID file /home/jh/a.C line 16 col 7 > align 8 context <function_decl 0x7ffff6b8e500 Run>> > full-name "virtual void D::Run()" > pending-inline-info 0x7ffff6ba42a0 > (mem:QI (symbol_ref/i:DI ("_ZN1D3RunEv") [flags 0x1] <function_decl > 0x7ffff6b8e500 Run>) [0 S1 A8])>> > > Note the differece in between type of address and the method RUN. This is > what > makes verifier unhappy. How to fix this? Should FE put there some NOP_EXPR > somewhere? Still devirtualizing should realize this case a lot earlier. Well - it's easy. Whoever does substitution needs to verify it can do so. Which of course is tricky with the stupid way we do substitute_and_fold ... Richard. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45605