------- Comment #11 from jakub at gcc dot gnu dot org  2010-06-24 16:21 -------
Created an attachment (id=20997)
 --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=20997&action=view)
unswitch-tuplification.patch

While the validity of the testcase is questionable, what unswitching does looks
certainly wrong.

I'm attaching two small patches that fix things I've found while reading
tree-ssa-loop-unswitch.

The real problem for this testcase though seems to be that there is no
unreachable block removal in between the unswitching levels, so it can very
well choose to unswitch on a condition that is never reachable in the
unswitched loop.
Say there is
while (...)
  {
    if (cond1)
      {
        if (cond2)
          A
        else
          B
      }
    else
      {
        if (cond3)
          C
        else
          D
      }
    E
  }

The first level chooses to unswitch on the cond1 condition, so we have:
if (cond1)  
  while (...)
    {  
      if (1 != 0)
        {
          if (cond2)
            A
          else
            B
        }
      else
        {
          if (cond3)
            C
          else
            D
        }
      E
    }
else
  while (...) 
    {
      if (0 != 0)
        { 
          if (cond2)
            A
          else
            B 
        }
      else
        {
          if (cond3)
            C
          else
            D
        }
      E
    }

Now, in the first loop if we decide to unswitch on cond3, it transforms this
into:
if (cond1)
  {
    if (cond3)
      while (...)
        {
          if (1 != 0)
            {
              if (cond2)
                A
              else
                B 
            }
          else
            { 
              if (1 != 0)
                C
              else
                D 
            }
          E  
        }    
    else   
      while (...)
        {
          if (1 != 0)
            {
              if (cond2)
                A
              else
                B 
            }
          else
            { 
              if (0 != 0)
                C
              else
                D 
            }
          E  
        }    
  }
else
  while (...)
    {
      if (0 != 0)
        {
          if (cond2)
            A
          else
            B 
        }
      else
        {     
          if (cond3)
            C
          else
            D 
        }
      E  
    }  

If cond3 tests some variable that is initialized only if cond1 is false, this
unswitching (besides not being very useful because cond3 is never tested when
cond1 is false in the original program) results in jumps on uninitialized
values comparison.

Anyway, this first patch tries to fix a bug caused by tuplification.  Before
tuplification, COND_EXPR_COND would be 0 or 1 when optimized, but 0 != 0 or 1
!= 0 condition never satisfies integer_zerop nor integer_nonzerop.  We could
fold it, but we already have predicates for this stuff.

This patch actually causes more unswitching to happen, because it never
unswitches on 0 != 0 or 1 != 0 conditions.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43866

Reply via email to