Hi! The following testcase ICEs, because we have a n argument PHI node referencing some BLOCK in its last gimple_phi_arg_location, then for the containing bb the number of predecessors decreases and thus the PHI has fewer arguments (but, nothing clears the argument location at that point), then tree-ssa-live.c removes unused blocks and removes the BLOCK that used to be referenced by that PHI previously (as it is no longer referenced), then the number of predecessors increases again, PHI nargs grows (but without resize_phi_node), but reserve_phi_args_for_new_edge doesn't clear the phi arg location either and nothing else sets it, so this means we refer to a dead BLOCK.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux (alternatively, the location can be cleared in remove_phi_arg_num instead). Ok for trunk? 2013-01-18 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/56029 * tree-phinodes.c (reserve_phi_args_for_new_edge): Set gimple_phi_arg_location for the new arg to UNKNOWN_LOCATION. * g++.dg/torture/pr56029.C: New test. --- gcc/tree-phinodes.c.jj 2013-01-11 09:02:35.000000000 +0100 +++ gcc/tree-phinodes.c 2013-01-18 17:41:36.896361044 +0100 @@ -312,6 +312,7 @@ reserve_phi_args_for_new_edge (basic_blo redirects edges, and then fixes up PHI arguments later in batch. */ SET_PHI_ARG_DEF (stmt, len - 1, NULL_TREE); + gimple_phi_arg_set_location (stmt, len - 1, UNKNOWN_LOCATION); stmt->gimple_phi.nargs++; } --- gcc/testsuite/g++.dg/torture/pr56029.C.jj 2013-01-18 17:44:26.727347502 +0100 +++ gcc/testsuite/g++.dg/torture/pr56029.C 2013-01-18 17:44:19.000000000 +0100 @@ -0,0 +1,126 @@ +// PR tree-optimization/56029 +// { dg-do compile } + +template <class T> +struct DefaultDeleter +{ + void operator () (T * ptr) { delete ptr; } +}; +template <class T, class D> +struct scoped_ptr_impl +{ + scoped_ptr_impl (T * p):data_ (p) {} + template <typename U, typename V> + scoped_ptr_impl (scoped_ptr_impl <U, V> *other):data_ (other->release (), get_deleter ()) {} + ~scoped_ptr_impl () { static_cast <D> (data_) (data_.ptr); } + void reset (T * p) { data_.ptr = p; } + D get_deleter () {} + T *release () { data_.ptr = __null; } + struct Data + : D + { + Data (T *) : ptr () {} + Data (T *, D) : D (), ptr () {} + T *ptr; + }; + Data data_; +}; +template <class T, class D = DefaultDeleter <T> > +struct scoped_ptr +{ + struct RValue + { + RValue (scoped_ptr * object):object (object) {} + scoped_ptr *object; + }; + scoped_ptr Pass () { return scoped_ptr ((this)); } + typedef T element_type; + typedef D deleter_type; + scoped_ptr () : impl_ (__null) {} + scoped_ptr (RValue rvalue) : impl_ (&rvalue.object->impl_) {} + void reset (element_type * p) { impl_.reset (p); } + scoped_ptr_impl <element_type, deleter_type> impl_; +}; +template <typename> +struct Callback; +struct ClientSocketFactory; +struct DatagramClientSocket; +struct DnsSocketPool +{ + scoped_ptr <DatagramClientSocket> CreateConnectedSocket (); + ClientSocketFactory *socket_factory_; +}; +int RandInt (int, int); +struct BindStateBase {}; +struct CallbackBase +{ + CallbackBase (BindStateBase *); + ~CallbackBase (); +}; +template <typename, typename, typename> +struct BindState; +template <typename R, typename A1, typename A2> +struct Callback <R (A1, A2)> : CallbackBase +{ + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback (BindState <Runnable, BindRunType, BoundArgsType> *bind_state) : CallbackBase (bind_state) {} +}; +typedef Callback <int (int, int)> +RandIntCallback; +struct ClientSocketFactory +{ + virtual DatagramClientSocket *CreateDatagramClientSocket (RandIntCallback) = 0; +}; +template <typename> +struct RunnableAdapter; +template <typename R, typename A1, typename A2> +struct RunnableAdapter <R (*) (A1, A2)> +{ + typedef R (RunType) (A1, A2); +}; +template <typename T> +struct FunctorTraits +{ + typedef RunnableAdapter <T> RunnableType; + typedef typename RunnableType::RunType RunType; +}; +template <typename T> +typename FunctorTraits <T>::RunnableType MakeRunnable (T) +{ +} +template <int, typename, typename> +struct Invoker; +template <typename StorageType, typename R, typename X1, typename X2> +struct Invoker <0, StorageType, R (X1, X2)> +{ + typedef R (UnboundRunType) (X1, X2); +}; +template <typename Runnable, typename RunType> +struct BindState <Runnable, RunType, void ()> : BindStateBase +{ + typedef Runnable RunnableType; + typedef Invoker <0, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + BindState (Runnable):runnable_ () {} + RunnableType runnable_; +}; +template <typename Functor> +Callback <typename BindState <typename FunctorTraits <Functor>::RunnableType, typename FunctorTraits <Functor>::RunType, void ()>::UnboundRunType> +Bind (Functor functor) +{ + typedef typename FunctorTraits <Functor>::RunnableType RunnableType; + typedef typename FunctorTraits <Functor>::RunType RunType; + typedef BindState <RunnableType, RunType, void ()> BindState; + Callback <typename BindState::UnboundRunType> (new BindState (MakeRunnable (functor))); +} +struct DatagramClientSocket +{ + virtual ~ DatagramClientSocket (); +}; +scoped_ptr <DatagramClientSocket> +DnsSocketPool::CreateConnectedSocket () +{ + scoped_ptr <DatagramClientSocket> socket; + socket.reset (socket_factory_->CreateDatagramClientSocket (Bind (RandInt))); + socket.Pass (); +} Jakub