]> git.ipfire.org Git - thirdparty/gcc.git/commit
loop-ch improvements, part 3
authorJan Hubicka <jh@suse.cz>
Thu, 20 Jul 2023 13:41:39 +0000 (15:41 +0200)
committerJan Hubicka <jh@suse.cz>
Thu, 20 Jul 2023 13:41:39 +0000 (15:41 +0200)
commitef28aadad6e5cff3d7494f3c97d435a6579a2e2d
tree57a93c1672af52b2cc5133122a01a52a7dd6dd78
parentd0de3bf9175877d6c51c94fe04662c6e031876e1
loop-ch improvements, part 3

Make tree-ssa-loop-ch understand if-combined conditionals (which
are quite common) and remove the IV-derived heuristics.  That heuristics is
quite dubious because every variable with PHI in header of integral or pointer
type is seen as IV, so in the first basic block we match all loop invariants as
invariants and everything that chagnes in loop as IV-like.

I think the heuristics was mostly there to make header duplication happen when
the exit conditional is constant false in the first iteration and with ranger
we can work this out in good enough precision.

The patch adds notion of "combined exit" which has conditional that is
and/or/xor of loop invariant exit and exit known to be false in first
iteration.  Copying these is a win since the loop conditional will simplify
in both copies.

It seems that those are usual bit or/and/xor and the code size accounting is
true only when the values have at most one bit set or when the static constant
and invariant versions are simple (such as all zeros).  I am not testing this,
so the code may be optimistic here.  I think it is not common enough to matter
and I can not think of correct condition that is not quite complex.

I also improved code size estimate not accounting non-conditionals that are
know to be constant in peeled copy and improved debug output.

This requires testsuite compensaiton.  uninit-pred-loop-1.c.C does:

/* { dg-do compile } */
/* { dg-options "-Wuninitialized -O2 -std=c++98" } */

extern int bar();
int foo(int n, int m)
{
 for (;;) {
   int err = ({int _err;
     for (int i = 0; i < 16; ++i) {
       if (m+i > n)
          break;
       _err = 17;
       _err = bar();
     }
     _err;
   });

   if (err == 0) return 17;
}

Before path we duplicate
       if (m+i > n)
which makes maybe-uninitialized warning to not be output.  I do not quite see
why copying this out would be a win, since it won't simlify.  Also I think the
warning is correct.  if m>n the loop will bail out before initializing _err and
it will be used unitialized.  I think it is bug elsewhere that header
duplication supresses this.

copy headers does:
int is_sorted(int *a, int n, int m, int k)
{
  for (int i = 0; i < n - 1 && m && k > i; i++)
    if (a[i] > a[i + 1])
      return 0;
  return 1;
}

it tests that all three for statement conditionals are duplicaed.  With patch
we no longer do k>i since it is not going to simplify.  So I added test
ensuring that k is positive.  Also the tests requires disabling if-combining and
vrp to avoid conditionals becoming combined ones. So I aded new version of test
that we now behave correctly aslo with if-combine.

ivopt_mult_2.c and ivopt_mult_1.c seems to require loop header
duplication for ivopts to behave particular way, so I also ensured by value
range that the header is duplicated.

Bootstrapped/regtested x86_64-linux, OK?

gcc/ChangeLog:

* tree-ssa-loop-ch.cc (edge_range_query): Rename to ...
(get_range_query): ... this one; do
(static_loop_exit): Add query parametr, turn ranger to reference.
(loop_static_stmt_p): New function.
(loop_static_op_p): New function.
(loop_iv_derived_p): Remove.
(loop_combined_static_and_iv_p): New function.
(should_duplicate_loop_header_p): Discover combined onditionals;
do not track iv derived; improve dumps.
(pass_ch::execute): Fix whitespace.

gcc/testsuite/ChangeLog:

* g++.dg/uninit-pred-loop-1_c.C: Allow warning.
* gcc.dg/tree-ssa/copy-headers-7.c: Add tests so exit conditition is
static; update template.
* gcc.dg/tree-ssa/ivopt_mult_1.c: Add test so exit condition is static.
* gcc.dg/tree-ssa/ivopt_mult_2.c: Add test so exit condition is static.
* gcc.dg/tree-ssa/copy-headers-8.c: New test.
gcc/testsuite/g++.dg/uninit-pred-loop-1_c.C
gcc/testsuite/gcc.dg/tree-ssa/copy-headers-7.c
gcc/testsuite/gcc.dg/tree-ssa/copy-headers-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1.c
gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2.c
gcc/tree-ssa-loop-ch.cc