{"id":809594,"url":"http://patchwork.ozlabs.org/api/patches/809594/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/alpine.LSU.2.20.1709041239400.14191@zhemvz.fhfr.qr/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<alpine.LSU.2.20.1709041239400.14191@zhemvz.fhfr.qr>","list_archive_url":null,"date":"2017-09-04T10:40:19","name":"Fix PR82060","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"fb997db9c8e503fa278cc86620a6fd7b52aff401","submitter":{"id":4338,"url":"http://patchwork.ozlabs.org/api/people/4338/?format=json","name":"Richard Biener","email":"rguenther@suse.de"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/alpine.LSU.2.20.1709041239400.14191@zhemvz.fhfr.qr/mbox/","series":[{"id":1353,"url":"http://patchwork.ozlabs.org/api/series/1353/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=1353","date":"2017-09-04T10:40:19","name":"Fix PR82060","version":1,"mbox":"http://patchwork.ozlabs.org/series/1353/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/809594/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/809594/checks/","tags":{},"related":[],"headers":{"Return-Path":"<gcc-patches-return-461397-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-461397-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"KdsjA+R8\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xm5wQ0y2vz9s8J\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon,  4 Sep 2017 20:40:36 +1000 (AEST)","(qmail 41451 invoked by alias); 4 Sep 2017 10:40:29 -0000","(qmail 41433 invoked by uid 89); 4 Sep 2017 10:40:28 -0000","from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by\n\tsourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tMon, 04 Sep 2017 10:40:22 +0000","from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254])\tby\n\tmx1.suse.de (Postfix) with ESMTP id 31BBBAAB6\tfor\n\t<gcc-patches@gcc.gnu.org>; Mon,  4 Sep 2017 10:40:20 +0000 (UTC)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:date\n\t:from:to:subject:message-id:mime-version:content-type; q=dns; s=\n\tdefault; b=rIoqiy2xY+1QMHArCsd0apDuAlV+nnLQY09TFpyzsRiJ/aE0x6bk/\n\ts9on2MdHiNu5vbjrKAFNEjCG5bOhUHk2f0R/e67ob7J1oQFZcQyVVPyU4dW46zrJ\n\tQkRdpsUAbes1XMMYj2rbHwv4EyOkzxRlsD8SC6/lkSThXwOG5WZonw=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:date\n\t:from:to:subject:message-id:mime-version:content-type; s=\n\tdefault; bh=YCC0JwT/XCDi014JIzSwCVgYQk4=; b=KdsjA+R8shARMl0MRxzV\n\tUY/J1K5A2iHXs8aBm55gIoJKszz/MqHwbxPiZWpS4NwqhNjeM/z71dp1hRx5s+Fn\n\t3bT/dN/UMnwLivyyQ/ZcZShBEX8S9NlengPmYZB7SL5sIKn+eBD3crpkaAX7H//V\n\t/bFIetBxpTobkeccHoj0HiU=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-11.1 required=5.0 tests=BAYES_00, GIT_PATCH_2,\n\tGIT_PATCH_3, KAM_ASCII_DIVIDERS, RP_MATCHES_RCVD,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=cb","X-HELO":"mx1.suse.de","Date":"Mon, 4 Sep 2017 12:40:19 +0200 (CEST)","From":"Richard Biener <rguenther@suse.de>","To":"gcc-patches@gcc.gnu.org","Subject":"[PATCH] Fix PR82060","Message-ID":"<alpine.LSU.2.20.1709041239400.14191@zhemvz.fhfr.qr>","User-Agent":"Alpine 2.20 (LSU 67 2015-01-07)","MIME-Version":"1.0","Content-Type":"text/plain; charset=US-ASCII"},"content":"The following fixes PR82060 but canonicalizing mems before dispatching\nto the devrit machinery.\n\nBootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.\n\nRichard.\n\n2017-09-04  Richard Biener  <rguenther@suse.de>\n\n\tPR tree-optimization/82060\n\t* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):\n\tMove devirtualization after stmt folding and before EH/AB/noreturn\n\tcleanup to get the stmt refs canonicalized.  Use a bool instead\n\tof gimple_modified_p since that doesn't work for NOPs.  Schedule\n\tNOPs generated by folding for removal.\n\n\t* g++.dg/torture/pr82060.C: New testcase.","diff":"Index: gcc/tree-ssa-pre.c\n===================================================================\n--- gcc/tree-ssa-pre.c\t(revision 251559)\n+++ gcc/tree-ssa-pre.c\t(working copy)\n@@ -4592,6 +4592,7 @@ eliminate_dom_walker::before_dom_childre\n       /* If we didn't replace the whole stmt (or propagate the result\n          into all uses), replace all uses on this stmt with their\n \t leaders.  */\n+      bool modified = false;\n       use_operand_p use_p;\n       ssa_op_iter iter;\n       FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)\n@@ -4613,7 +4614,7 @@ eliminate_dom_walker::before_dom_childre\n \t\t  || !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))))\n \t    {\n \t      propagate_value (use_p, sprime);\n-\t      gimple_set_modified (stmt, true);\n+\t      modified = true;\n \t      if (TREE_CODE (sprime) == SSA_NAME\n \t\t  && !is_gimple_debug (stmt))\n \t\tgimple_set_plf (SSA_NAME_DEF_STMT (sprime),\n@@ -4621,8 +4622,56 @@ eliminate_dom_walker::before_dom_childre\n \t    }\n \t}\n \n+      /* Fold the stmt if modified, this canonicalizes MEM_REFs we propagated\n+         into which is a requirement for the IPA devirt machinery.  */\n+      gimple *old_stmt = stmt;\n+      if (modified)\n+\t{\n+\t  /* If a formerly non-invariant ADDR_EXPR is turned into an\n+\t     invariant one it was on a separate stmt.  */\n+\t  if (gimple_assign_single_p (stmt)\n+\t      && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)\n+\t    recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));\n+\t  gimple_stmt_iterator prev = gsi;\n+\t  gsi_prev (&prev);\n+\t  if (fold_stmt (&gsi))\n+\t    {\n+\t      /* fold_stmt may have created new stmts inbetween\n+\t\t the previous stmt and the folded stmt.  Mark\n+\t\t all defs created there as varying to not confuse\n+\t\t the SCCVN machinery as we're using that even during\n+\t\t elimination.  */\n+\t      if (gsi_end_p (prev))\n+\t\tprev = gsi_start_bb (b);\n+\t      else\n+\t\tgsi_next (&prev);\n+\t      if (gsi_stmt (prev) != gsi_stmt (gsi))\n+\t\tdo\n+\t\t  {\n+\t\t    tree def;\n+\t\t    ssa_op_iter dit;\n+\t\t    FOR_EACH_SSA_TREE_OPERAND (def, gsi_stmt (prev),\n+\t\t\t\t\t       dit, SSA_OP_ALL_DEFS)\n+\t\t      /* As existing DEFs may move between stmts\n+\t\t\t we have to guard VN_INFO_GET.  */\n+\t\t      if (! has_VN_INFO (def))\n+\t\t\tVN_INFO_GET (def)->valnum = def;\n+\t\t    if (gsi_stmt (prev) == gsi_stmt (gsi))\n+\t\t      break;\n+\t\t    gsi_next (&prev);\n+\t\t  }\n+\t\twhile (1);\n+\t    }\n+\t  stmt = gsi_stmt (gsi);\n+\t  /* In case we folded the stmt away schedule the NOP for removal.  */\n+\t  if (gimple_nop_p (stmt))\n+\t    el_to_remove.safe_push (stmt);\n+\t}\n+\n       /* Visit indirect calls and turn them into direct calls if\n-\t possible using the devirtualization machinery.  */\n+\t possible using the devirtualization machinery.  Do this before\n+\t checking for required EH/abnormal/noreturn cleanup as devird\n+\t may expose more of those.  */\n       if (gcall *call_stmt = dyn_cast <gcall *> (stmt))\n \t{\n \t  tree fn = gimple_call_fn (call_stmt);\n@@ -4631,24 +4680,21 @@ eliminate_dom_walker::before_dom_childre\n \t      && virtual_method_call_p (fn))\n \t    {\n \t      tree otr_type = obj_type_ref_class (fn);\n+\t      unsigned HOST_WIDE_INT otr_tok\n+\t\t= tree_to_uhwi (OBJ_TYPE_REF_TOKEN (fn));\n \t      tree instance;\n-\t      ipa_polymorphic_call_context context (current_function_decl, fn, stmt, &instance);\n+\t      ipa_polymorphic_call_context context (current_function_decl,\n+\t\t\t\t\t\t    fn, stmt, &instance);\n+\t      context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn),\n+\t\t\t\t\totr_type, stmt);\n \t      bool final;\n-\n-\t      context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt);\n-\n-\t      vec <cgraph_node *>targets\n+\t      vec <cgraph_node *> targets\n \t\t= possible_polymorphic_call_targets (obj_type_ref_class (fn),\n-\t\t\t\t\t\t     tree_to_uhwi\n-\t\t\t\t\t\t       (OBJ_TYPE_REF_TOKEN (fn)),\n-\t\t\t\t\t\t     context,\n-\t\t\t\t\t\t     &final);\n+\t\t\t\t\t\t     otr_tok, context, &final);\n \t      if (dump_file)\n \t\tdump_possible_polymorphic_call_targets (dump_file, \n \t\t\t\t\t\t\tobj_type_ref_class (fn),\n-\t\t\t\t\t\t\ttree_to_uhwi\n-\t\t\t\t\t\t\t  (OBJ_TYPE_REF_TOKEN (fn)),\n-\t\t\t\t\t\t\tcontext);\n+\t\t\t\t\t\t\totr_tok, context);\n \t      if (final && targets.length () <= 1 && dbg_cnt (devirt))\n \t\t{\n \t\t  tree fn;\n@@ -4658,7 +4704,7 @@ eliminate_dom_walker::before_dom_childre\n \t\t    fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);\n \t\t  if (dump_enabled_p ())\n \t\t    {\n-\t\t      location_t loc = gimple_location_safe (stmt);\n+\t\t      location_t loc = gimple_location (stmt);\n \t\t      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,\n \t\t\t\t       \"converting indirect call to \"\n \t\t\t\t       \"function %s\\n\",\n@@ -4675,50 +4721,13 @@ eliminate_dom_walker::before_dom_childre\n \t\t\t  == void_type_node))\n \t\t    gimple_call_set_fntype (call_stmt, TREE_TYPE (fn));\n \t\t  maybe_remove_unused_call_args (cfun, call_stmt);\n-\t\t  gimple_set_modified (stmt, true);\n+\t\t  modified = true;\n \t\t}\n \t    }\n \t}\n \n-      if (gimple_modified_p (stmt))\n+      if (modified)\n \t{\n-\t  /* If a formerly non-invariant ADDR_EXPR is turned into an\n-\t     invariant one it was on a separate stmt.  */\n-\t  if (gimple_assign_single_p (stmt)\n-\t      && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)\n-\t    recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));\n-\t  gimple *old_stmt = stmt;\n-\t  gimple_stmt_iterator prev = gsi;\n-\t  gsi_prev (&prev);\n-\t  if (fold_stmt (&gsi))\n-\t    {\n-\t      /* fold_stmt may have created new stmts inbetween\n-\t\t the previous stmt and the folded stmt.  Mark\n-\t\t all defs created there as varying to not confuse\n-\t\t the SCCVN machinery as we're using that even during\n-\t\t elimination.  */\n-\t      if (gsi_end_p (prev))\n-\t\tprev = gsi_start_bb (b);\n-\t      else\n-\t\tgsi_next (&prev);\n-\t      if (gsi_stmt (prev) != gsi_stmt (gsi))\n-\t\tdo\n-\t\t  {\n-\t\t    tree def;\n-\t\t    ssa_op_iter dit;\n-\t\t    FOR_EACH_SSA_TREE_OPERAND (def, gsi_stmt (prev),\n-\t\t\t\t\t       dit, SSA_OP_ALL_DEFS)\n-\t\t      /* As existing DEFs may move between stmts\n-\t\t\t we have to guard VN_INFO_GET.  */\n-\t\t      if (! has_VN_INFO (def))\n-\t\t\tVN_INFO_GET (def)->valnum = def;\n-\t\t    if (gsi_stmt (prev) == gsi_stmt (gsi))\n-\t\t      break;\n-\t\t    gsi_next (&prev);\n-\t\t  }\n-\t\twhile (1);\n-\t    }\n-\t  stmt = gsi_stmt (gsi);\n \t  /* When changing a call into a noreturn call, cfg cleanup\n \t     is needed to fix up the noreturn call.  */\n \t  if (!was_noreturn\nIndex: gcc/testsuite/g++.dg/torture/pr82060.C\n===================================================================\n--- gcc/testsuite/g++.dg/torture/pr82060.C\t(nonexistent)\n+++ gcc/testsuite/g++.dg/torture/pr82060.C\t(working copy)\n@@ -0,0 +1,32 @@\n+// { dg-do compile }\n+\n+struct A\n+{\n+  char a[1]; // must be char array\n+};\n+\n+struct B\n+{\n+  A& a() { return ma; } // must be accessed through a getter\n+  A ma;\n+};\n+\n+struct C\n+{\n+  B& b() { return mb; } // must be accessed through a getter\n+  B mb;\n+};\n+\n+struct D\n+{\n+  virtual A getA() = 0; // must be virtual\n+};\n+\n+void\n+foo(D& d) // The D object must not be created locally\n+          // (so that getA implementation is not known at compile time?)\n+{\n+  C c;\n+  for (;;) // must be in a loop\n+    c.b().a() = d.getA();\n+}\n","prefixes":[]}