------- 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

Reply via email to