diff mbox

Fix PR57235

Message ID alpine.LNX.2.00.1305131240290.24881@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener May 13, 2013, 10:45 a.m. UTC
This fixes a virtual SSA updating problem with sinking clobbers.
Namely when sinking into a block with multiple predecessors and
no virtual use we lack a convenient PHI node that serves as a
merge of the virtual operands from the predecessors.  The following
patch gives up sinking clobbers in this case (alternatively
we can remove all clobbers).  Any preference here?  I'm wondering
when sinking a clobber into a block with multiple preds is good.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Thanks,
Richard.

2013-05-13  Richard Biener  <rguenther@suse.de>

	PR middle-end/57235
	* tree-eh.c (sink_clobbers): Give up for successors with
	multiple predecessors and no virtual uses.

	* g++.dg/torture/pr57235.C: New testcase.
diff mbox

Patch

Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c	(revision 198815)
+++ gcc/tree-eh.c	(working copy)
@@ -3360,6 +3360,11 @@  sink_clobbers (basic_block bb)
 	}
     }
 
+  /* ???  If we have multiple predecessors but no virtual PHI we cannot
+     easily update virtual SSA form.  */
+  if (!vphi && !single_pred_p (succbb))
+    return 0;
+
   dgsi = gsi_after_labels (succbb);
   gsi = gsi_last_bb (bb);
   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
Index: gcc/testsuite/g++.dg/torture/pr57235.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr57235.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr57235.C	(working copy)
@@ -0,0 +1,156 @@ 
+// { dg-do compile }
+
+namespace std
+{
+  template < class _Elem > struct char_traits
+  {
+  };
+  struct _Container_base
+  {
+  };
+    template < class _Ty > struct _Allocator_base
+  {
+  };
+    template < class _Ty > class allocator:public _Allocator_base < _Ty >
+  {
+  };
+  class _String_base:public _Container_base
+  {
+  };
+template < class _Ty, class _Alloc > class _String_val:public _String_base
+  {
+  };
+template < class _Elem, class _Traits, class _Ax > class basic_string:public _String_val < _Elem,
+    _Ax
+    >
+  {
+  public:typedef basic_string < _Elem, _Traits, _Ax > _Myt;
+    typedef _String_val < _Elem, _Ax > _Mybase;
+    basic_string (const _Elem * _Ptr):_Mybase ()
+    {
+    }
+  };
+  typedef basic_string < char, char_traits < char >,
+    allocator < char > >string;
+}
+
+
+namespace google
+{
+  namespace protobuf
+  {
+    namespace internal
+    {
+      template < class C > class scoped_ptr
+      {
+      public:typedef C element_type;
+      explicit scoped_ptr (C * p = __null):ptr_ (p)
+	{
+	}
+	 ~scoped_ptr ()
+	{
+	  delete ptr_;
+	}
+	C *get () const
+	{
+	  return ptr_;
+	}
+      private:  C * ptr_;
+      };
+    }
+    using internal::scoped_ptr;
+    enum LogLevel
+    {
+      LOGLEVEL_INFO, LOGLEVEL_WARNING, LOGLEVEL_ERROR, LOGLEVEL_FATAL,
+	LOGLEVEL_DFATAL = LOGLEVEL_ERROR
+    };
+    namespace internal
+    {
+      class LogMessage
+      {
+      public:LogMessage (LogLevel level, const char *filename,
+		    int line);
+	 ~LogMessage ();
+	  LogMessage & operator<< (const std::string & value);
+      };
+      class LogFinisher
+      {
+      public:void operator= (LogMessage & other);
+      };
+    }
+    using namespace std;
+    class Descriptor
+    {
+    };
+    class FieldDescriptor
+    {
+    public:
+      const Descriptor *message_type () const;
+      string DebugString () const;
+    };
+    class MessageLite
+    {
+    };
+    class Message:public MessageLite
+    {
+    public:inline Message ()
+      {
+      }
+      virtual ~ Message ();
+      virtual Message *New () const = 0;
+    };
+    class MessageFactory
+    {
+    };
+    class UnknownFieldSet
+    {
+    };
+    class DynamicMessageFactory:public MessageFactory
+    {
+    public:DynamicMessageFactory ();
+      const Message *GetPrototype (const Descriptor * type);
+    };
+    namespace io
+    {
+      class ErrorCollector
+      {
+      public:inline ErrorCollector ()
+	{
+	}
+	virtual ~ ErrorCollector ();
+      };
+    }
+    class DescriptorBuilder
+    {
+      class OptionInterpreter
+      {
+	bool SetAggregateOption (const FieldDescriptor * option_field,
+				 UnknownFieldSet * unknown_fields);
+	DynamicMessageFactory dynamic_factory_;
+      };
+    };
+    namespace
+    {
+      class AggregateErrorCollector:public io::ErrorCollector
+      {
+      };
+    }
+    bool DescriptorBuilder::OptionInterpreter::
+      SetAggregateOption (const FieldDescriptor * option_field,
+			  UnknownFieldSet * unknown_fields)
+    {
+      const Descriptor *type = option_field->message_type ();
+      scoped_ptr < Message >
+	dynamic (dynamic_factory_.GetPrototype (type)->New ());
+      !(!(dynamic.get () !=
+	  __null)) ? (void) 0 : ::google::protobuf::internal::
+	LogFinisher () =::google::protobuf::internal::LogMessage (::google::
+								  protobuf::
+								  LOGLEVEL_FATAL,
+								  "descriptor.cc",
+								  4396) <<
+	option_field->DebugString ();
+      AggregateErrorCollector collector;
+    }
+  }
+}