This is a regression present on the mainline in the form of a segfault on the 
attached C testcase with -O2 -fnon-call-exceptions -ftracer.  The GIMPLE SSA 
store merging pass blows up when it is rewriting the stores because it didn't 
realize that they don't belong to the same EH region.

Fixed by refusing to merge them.  Tested on x86-64/Linux, pre-approved by 
Jakub and applied on the mainline.


2019-04-23  Eric Botcazou  <ebotca...@adacore.com>

        PR tree-optimization/94717
        * gimple-ssa-store-merging.c (try_coalesce_bswap): Return false if one
        of the stores doesn't have the same landing pad number as the first.
        (coalesce_immediate_stores): Do not try to coalesce the store using
        bswap if it doesn't have the same landing pad number as the first.


2019-04-23  Eric Botcazou  <ebotca...@adacore.com>

        * g++.dg/opt/store-merging-4.C: New test.

-- 
Eric Botcazou
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index a6687cd9c98..25753517cc6 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -2435,6 +2435,7 @@ imm_store_chain_info::try_coalesce_bswap (merged_store_group *merged_store,
   for (unsigned int i = first + 1; i < len; ++i)
     {
       if (m_store_info[i]->bitpos != m_store_info[first]->bitpos + width
+	  || m_store_info[i]->lp_nr != merged_store->lp_nr
 	  || m_store_info[i]->ins_stmt == NULL)
 	return false;
       width += m_store_info[i]->bitsize;
@@ -2682,6 +2683,7 @@ imm_store_chain_info::coalesce_immediate_stores ()
       if (info->bitpos == merged_store->start + merged_store->width
 	  && merged_store->stores.length () == 1
 	  && merged_store->stores[0]->ins_stmt != NULL
+	  && info->lp_nr == merged_store->lp_nr
 	  && info->ins_stmt != NULL)
 	{
 	  unsigned int try_size;
// PR tree-optimization/94717
// Reported by Zdenek Sojka <zso...@seznam.cz>

// { dg-do compile }
// { dg-options "-O2 -fnon-call-exceptions -ftracer" }

int abs (int);

static inline void
bar (int d)
{
  d && abs (d);
}

struct S
{
  int a;
  int b;
  int c;
  S (unsigned a, unsigned b) : a (a), b (b) { }
};

void
foo (S *x)
{
  bar (x->c);
  new S (x->a, x->b);
  bar (0);
}

Reply via email to