OSDN Git Service

2010-09-21 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Sep 2010 09:52:00 +0000 (09:52 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Sep 2010 09:52:00 +0000 (09:52 +0000)
PR tree-optimization/45580
* tree-ssa-propagate.c (substitute_and_fold): Always replace
regular uses.
* gimple-fold.c (gimple_fold_obj_type_ref): For a BINFO without
virtuals fold the call into a regular indirect one.

* g++.dg/torture/pr45580.C: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164474 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gimple-fold.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr45580.C [new file with mode: 0644]
gcc/tree-ssa-propagate.c

index 3b8d418..7585ee6 100644 (file)
@@ -1,3 +1,11 @@
+2010-09-21  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/45580
+       * tree-ssa-propagate.c (substitute_and_fold): Always replace
+       regular uses.
+       * gimple-fold.c (gimple_fold_obj_type_ref): For a BINFO without
+       virtuals fold the call into a regular indirect one.
+
 2010-09-20  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR rtl-optimization/42775
index 8faadcc..896f508 100644 (file)
@@ -1471,6 +1471,9 @@ gimple_fold_obj_type_ref (tree ref, tree known_type)
   if (binfo)
     {
       HOST_WIDE_INT token = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+      /* If there is no virtual methods fold this to an indirect call.  */
+      if (!BINFO_VIRTUALS (binfo))
+       return OBJ_TYPE_REF_EXPR (ref);
       return gimple_fold_obj_type_ref_known_binfo (token, binfo);
     }
   else
index ac22fff..b00b891 100644 (file)
@@ -1,3 +1,8 @@
+2010-09-21  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/45580
+       * g++.dg/torture/pr45580.C: New testcase.
+
 2010-09-21  Uros Bizjak  <ubizjak@gmail.com>
 
        * lib/gcc-dg.exp (clanup-stack-usage): Really remove .su files.
diff --git a/gcc/testsuite/g++.dg/torture/pr45580.C b/gcc/testsuite/g++.dg/torture/pr45580.C
new file mode 100644 (file)
index 0000000..c3af491
--- /dev/null
@@ -0,0 +1,50 @@
+// { dg-do compile }
+
+namespace std {
+    typedef __SIZE_TYPE__ size_t;
+}
+inline void* operator new(std::size_t, void* __p) throw() {
+    return __p;
+}
+class Noncopyable  { };
+struct CollectorCell { };
+template<typename T> class PassRefPtr {
+public:
+    T* releaseRef() const { }
+};
+template <typename T> class NonNullPassRefPtr {
+public:
+    template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o)
+       : m_ptr(o.releaseRef()) { }
+    mutable T* m_ptr;
+};
+struct ClassInfo;
+class JSValue { };
+JSValue jsNull();
+class Structure;
+class JSGlobalData {
+    static void storeVPtrs();
+};
+class JSCell : public Noncopyable {
+    friend class JSObject;
+    friend class JSGlobalData;
+    virtual ~JSCell();
+};
+class JSObject : public JSCell {
+public:
+    explicit JSObject(NonNullPassRefPtr<Structure>);
+    static PassRefPtr<Structure> createStructure(JSValue prototype) { }
+};
+class JSByteArray : public JSObject {
+    friend class JSGlobalData;
+    enum VPtrStealingHackType { VPtrStealingHack };
+    JSByteArray(VPtrStealingHackType)
+       : JSObject(createStructure(jsNull())), m_classInfo(0) { }
+    const ClassInfo* m_classInfo;
+};
+void JSGlobalData::storeVPtrs() {
+    CollectorCell cell;
+    void* storage = &cell;
+    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
+    jsByteArray->~JSCell();
+}
index e08d2e7..c97960c 100644 (file)
@@ -1122,12 +1122,12 @@ substitute_and_fold (ssa_prop_get_value_fn get_value_fn,
            {
              did_replace = true;
              prop_stats.num_stmts_folded++;
+             stmt = gsi_stmt (oldi);
+             update_stmt (stmt);
            }
 
-         /* Only replace real uses if we couldn't fold the
-            statement using value range information.  */
-         if (get_value_fn
-             && !did_replace)
+         /* Replace real uses in the statement.  */
+         if (get_value_fn)
            did_replace |= replace_uses_in (stmt, get_value_fn);
 
          /* If we made a replacement, fold the statement.  */