Patchwork Fix phi arg location handling (PR tree-optimization/56029)

login
register
mail settings
Submitter Jakub Jelinek
Date Jan. 18, 2013, 8:14 p.m.
Message ID <20130118201442.GD7269@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/213741/
State New
Headers show

Comments

Jakub Jelinek - Jan. 18, 2013, 8:14 p.m.
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  <jakub@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.


	Jakub
Jeff Law - Jan. 18, 2013, 8:19 p.m.
On 01/18/2013 01:14 PM, Jakub Jelinek wrote:
> 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  <jakub@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.
OK.
Jeff

Patch

--- 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 ();
+}