public inbox for gcc-regression@sourceware.org
help / color / mirror / Atom feed
* [TCWG CI] Regression caused by gcc: middle-end: Support recognition of three-way max/min.
@ 2022-08-04  5:34 ci_notify
  0 siblings, 0 replies; only message in thread
From: ci_notify @ 2022-08-04  5:34 UTC (permalink / raw)
  To: Tamar Christina; +Cc: gcc-regression

[TCWG CI] Regression caused by gcc: middle-end: Support recognition of three-way max/min.:
commit 9bb19e143cfe8863e2e79d4176b5d7e997b08c5f
Author: Tamar Christina <tamar.christina@arm.com>

    middle-end: Support recognition of three-way max/min.

Results regressed to
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
# 00:04:30 make[3]: [Makefile:1786: aarch64-unknown-linux-gnu/bits/largefile-config.h] Error 1 (ignored)
# 00:04:30 make[3]: [Makefile:1787: aarch64-unknown-linux-gnu/bits/largefile-config.h] Error 1 (ignored)
# 00:06:50 /home/tcwg-buildslave/workspace/tcwg_gnu_11/abe/snapshots/gcc.git~master/libdecnumber/decNumber.c:7342:13: internal compiler error: in gimple_phi_arg, at gimple.h:4594
# 00:06:50 make[3]: *** [Makefile:195: decNumber.o] Error 1
# 00:06:50 make[2]: *** [Makefile:11459: all-stage2-libdecnumber] Error 2
# 00:07:06 make[1]: *** [Makefile:25739: stage2-bubble] Error 2
# 00:07:06 make: *** [Makefile:1072: all] Error 2

from
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe bootstrap_O1:
2

THIS IS THE END OF INTERESTING STUFF.  BELOW ARE LINKS TO BUILDS, REPRODUCTION INSTRUCTIONS, AND THE RAW COMMIT.

This commit has regressed these CI configurations:
 - tcwg_gcc_bootstrap/master-aarch64-bootstrap_O1

First_bad build: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstrap_O1/5/artifact/artifacts/build-9bb19e143cfe8863e2e79d4176b5d7e997b08c5f/
Last_good build: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstrap_O1/5/artifact/artifacts/build-b6df113247b9f3f7c3db0e65c481dad5bcfddfb4/
Baseline build: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstrap_O1/5/artifact/artifacts/build-baseline/
Even more details: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstrap_O1/5/artifact/artifacts/

Reproduce builds:
<cut>
mkdir investigate-gcc-9bb19e143cfe8863e2e79d4176b5d7e997b08c5f
cd investigate-gcc-9bb19e143cfe8863e2e79d4176b5d7e997b08c5f

# Fetch scripts
git clone https://git.linaro.org/toolchain/jenkins-scripts

# Fetch manifests and test.sh script
mkdir -p artifacts/manifests
curl -o artifacts/manifests/build-baseline.sh https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstrap_O1/5/artifact/artifacts/manifests/build-baseline.sh --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstrap_O1/5/artifact/artifacts/manifests/build-parameters.sh --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstrap_O1/5/artifact/artifacts/test.sh --fail
chmod +x artifacts/test.sh

# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_gnu-build.sh @@ artifacts/manifests/build-baseline.sh

# Save baseline build state (which is then restored in artifacts/test.sh)
mkdir -p ./bisect
rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /gcc/ ./ ./bisect/baseline/

cd gcc

# Reproduce first_bad build
git checkout --detach 9bb19e143cfe8863e2e79d4176b5d7e997b08c5f
../artifacts/test.sh

# Reproduce last_good build
git checkout --detach b6df113247b9f3f7c3db0e65c481dad5bcfddfb4
../artifacts/test.sh

cd ..
</cut>

Full commit (up to 1000 lines):
<cut>
commit 9bb19e143cfe8863e2e79d4176b5d7e997b08c5f
Author: Tamar Christina <tamar.christina@arm.com>
Date:   Wed Aug 3 16:00:39 2022 +0100

    middle-end: Support recognition of three-way max/min.
    
    This patch adds support for three-way min/max recognition in phi-opts.
    
    Concretely for e.g.
    
    #include <stdint.h>
    
    uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) {
            uint8_t  xk;
        if (xc < xm) {
            xk = (uint8_t) (xc < xy ? xc : xy);
        } else {
            xk = (uint8_t) (xm < xy ? xm : xy);
        }
        return xk;
    }
    
    we generate:
    
      <bb 2> [local count: 1073741824]:
      _5 = MIN_EXPR <xc_1(D), xy_3(D)>;
      _7 = MIN_EXPR <xm_2(D), _5>;
      return _7;
    
    instead of
    
      <bb 2>:
      if (xc_2(D) < xm_3(D))
        goto <bb 3>;
      else
        goto <bb 4>;
    
      <bb 3>:
      xk_5 = MIN_EXPR <xc_2(D), xy_4(D)>;
      goto <bb 5>;
    
      <bb 4>:
      xk_6 = MIN_EXPR <xm_3(D), xy_4(D)>;
    
      <bb 5>:
      # xk_1 = PHI <xk_5(3), xk_6(4)>
      return xk_1;
    
    The same function also immediately deals with turning a minimization problem
    into a maximization one if the results are inverted.  We do this here since
    doing it in match.pd would end up changing the shape of the BBs and adding
    additional instructions which would prevent various optimizations from working.
    
    gcc/ChangeLog:
    
            * tree-ssa-phiopt.cc (minmax_replacement): Optionally search for the phi
            sequence of a three-way conditional.
            (replace_phi_edge_with_variable): Support diamonds.
            (tree_ssa_phiopt_worker): Detect diamond phi structure for three-way
            min/max.
            (strip_bit_not, invert_minmax_code): New.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/split-path-1.c: Disable phi-opts so we don't optimize
            code away.
            * gcc.dg/tree-ssa/minmax-10.c: New test.
            * gcc.dg/tree-ssa/minmax-11.c: New test.
            * gcc.dg/tree-ssa/minmax-12.c: New test.
            * gcc.dg/tree-ssa/minmax-13.c: New test.
            * gcc.dg/tree-ssa/minmax-14.c: New test.
            * gcc.dg/tree-ssa/minmax-15.c: New test.
            * gcc.dg/tree-ssa/minmax-16.c: New test.
            * gcc.dg/tree-ssa/minmax-3.c: New test.
            * gcc.dg/tree-ssa/minmax-4.c: New test.
            * gcc.dg/tree-ssa/minmax-5.c: New test.
            * gcc.dg/tree-ssa/minmax-6.c: New test.
            * gcc.dg/tree-ssa/minmax-7.c: New test.
            * gcc.dg/tree-ssa/minmax-8.c: New test.
            * gcc.dg/tree-ssa/minmax-9.c: New test.
---
 gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c    |  20 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c    |  21 +++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c    |  20 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c    |  19 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c    |  21 +++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c    |  21 +++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c    |  17 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c     |  17 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c     |  17 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c     |  17 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c     |  17 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c     |  16 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c     |  17 ++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c     |  20 ++
 gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c |   2 +-
 gcc/tree-ssa-phiopt.cc                       | 263 +++++++++++++++++++++++++--
 16 files changed, 505 insertions(+), 20 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c
new file mode 100644
index 00000000000..58995368441
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+#include <stdint.h>
+
+uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) {
+    uint8_t	 xk;
+    xc=~xc;
+    xm=~xm;
+    xy=~xy;
+    if (xc > xm) {
+        xk = (uint8_t) (xc > xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm > xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c
new file mode 100644
index 00000000000..1c2ef01b5d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) {
+	uint8_t	 xk;
+    xc=~xc;
+    xm=~xm;
+    xy=~xy;
+    if (xc > xm) {
+        xk = (uint8_t) (xc < xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c
new file mode 100644
index 00000000000..3d0c07d9b57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) {
+        uint8_t  xk;
+    xc=~xc;
+    xm=~xm;
+    xy=~xy;
+    if (xc > xm) {
+        xk = (uint8_t) (xy < xc ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c
new file mode 100644
index 00000000000..c0d0f27c802
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) {
+	uint8_t	 xk;
+    xc=~xc;
+    xm=~xm;
+    xy=~xy;
+    if (xc > xm) {
+        xk = (uint8_t) (xc > xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c
new file mode 100644
index 00000000000..9c0cadbf7e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) {
+        uint8_t  xk;
+    xc=~xc;
+    xm=~xm;
+    xy=~xy;
+    if (xc < xm) {
+        xk = (uint8_t) (xc > xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm > xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c
new file mode 100644
index 00000000000..1d97a16564f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy, bool m) {
+    uint8_t  xk;
+    if (xc)
+      {
+        if (xc < xm) {
+            xk = (uint8_t) (xc < xy ? xc : xy);
+        } else {
+            xk = (uint8_t) (xm < xy ? xm : xy);
+        }
+      }
+
+    return xk;
+}
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c
new file mode 100644
index 00000000000..89377a2cb34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt -g" } */
+
+#include <stdint.h>
+
+uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) {
+	uint8_t	 xk;
+    if (xc < xm) {
+        xk = (uint8_t) (xc < xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c
new file mode 100644
index 00000000000..de3b2e946e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) {
+	uint8_t	 xk;
+    if (xc < xm) {
+        xk = (uint8_t) (xc < xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c
new file mode 100644
index 00000000000..0b6d667be86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) {
+    uint8_t	 xk;
+    if (xc > xm) {
+        xk = (uint8_t) (xc > xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm > xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 0 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c
new file mode 100644
index 00000000000..650601a3cc7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) {
+	uint8_t	 xk;
+    if (xc > xm) {
+        xk = (uint8_t) (xc < xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c
new file mode 100644
index 00000000000..a628f6d9922
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) {
+        uint8_t  xk;
+    if (xc > xm) {
+        xk = (uint8_t) (xy < xc ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c
new file mode 100644
index 00000000000..cb42412c4ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) {
+	uint8_t	 xk;
+    if (xc > xm) {
+        xk = (uint8_t) (xc > xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c
new file mode 100644
index 00000000000..9cd050e9323
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt" } */
+
+#include <stdint.h>
+
+uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) {
+        uint8_t  xk;
+    if (xc < xm) {
+        xk = (uint8_t) (xc > xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm > xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c
new file mode 100644
index 00000000000..24f580271c3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+#include <stdint.h>
+
+uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) {
+	uint8_t	 xk;
+    xc=~xc;
+    xm=~xm;
+    xy=~xy;
+    if (xc < xm) {
+        xk = (uint8_t) (xc < xy ? xc : xy);
+    } else {
+        xk = (uint8_t) (xm < xy ? xm : xy);
+    }
+    return xk;
+}
+
+/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c b/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c
index 8b23ef4c7a3..902dde44a50 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details --param max-jump-thread-duplication-stmts=20" } */
+/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details --param max-jump-thread-duplication-stmts=20 -fno-ssa-phiopt" } */
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 2f4bebe7655..a8e55e04064 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -63,8 +63,8 @@ static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree,
 						gimple *);
 static int value_replacement (basic_block, basic_block,
 			      edge, edge, gphi *, tree, tree);
-static bool minmax_replacement (basic_block, basic_block,
-				edge, edge, gphi *, tree, tree);
+static bool minmax_replacement (basic_block, basic_block, basic_block,
+				edge, edge, gphi *, tree, tree, bool);
 static bool spaceship_replacement (basic_block, basic_block,
 				   edge, edge, gphi *, tree, tree);
 static bool cond_removal_in_builtin_zero_pattern (basic_block, basic_block,
@@ -200,6 +200,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
       basic_block bb1, bb2;
       edge e1, e2;
       tree arg0, arg1;
+      bool diamond_p = false;
 
       bb = bb_order[i];
 
@@ -266,6 +267,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
 	    hoist_adjacent_loads (bb, bb1, bb2, bb3);
 	  continue;
 	}
+      else if (EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest
+	       && !empty_block_p (bb1))
+	diamond_p = true;
       else
 	continue;
 
@@ -294,10 +298,13 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
 	}
       else
 	{
-	  gimple_seq phis = phi_nodes (bb2);
 	  gimple_stmt_iterator gsi;
 	  bool candorest = true;
 
+	  /* Check that we're looking for nested phis.  */
+	  basic_block merge = diamond_p ? EDGE_SUCC (bb2, 0)->dest : bb2;
+	  gimple_seq phis = phi_nodes (merge);
+
 	  /* Value replacement can work with more than one PHI
 	     so try that first. */
 	  if (!early_p)
@@ -317,6 +324,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
 	  if (!candorest)
 	    continue;
 
+	  e2 = diamond_p ? EDGE_SUCC (bb2, 0) : e2;
 	  phi = single_non_singleton_phi_for_edges (phis, e1, e2);
 	  if (!phi)
 	    continue;
@@ -330,6 +338,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
 
 	  gphi *newphi;
 	  if (single_pred_p (bb1)
+	      && !diamond_p
 	      && (newphi = factor_out_conditional_conversion (e1, e2, phi,
 							      arg0, arg1,
 							      cond_stmt)))
@@ -344,20 +353,25 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
 	    }
 
 	  /* Do the replacement of conditional if it can be done.  */
-	  if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
+	  if (!early_p
+	      && !diamond_p
+	      && two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
 	    cfgchanged = true;
-	  else if (match_simplify_replacement (bb, bb1, e1, e2, phi,
-					       arg0, arg1,
-					       early_p))
+	  else if (!diamond_p
+		   && match_simplify_replacement (bb, bb1, e1, e2, phi,
+						  arg0, arg1, early_p))
 	    cfgchanged = true;
 	  else if (!early_p
+		   && !diamond_p
 		   && single_pred_p (bb1)
 		   && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2,
 							    phi, arg0, arg1))
 	    cfgchanged = true;
-	  else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+	  else if (minmax_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1,
+				       diamond_p))
 	    cfgchanged = true;
 	  else if (single_pred_p (bb1)
+		   && !diamond_p
 		   && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
 	    cfgchanged = true;
 	}
@@ -422,12 +436,23 @@ replace_phi_edge_with_variable (basic_block cond_block,
   SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree);
 
   /* Remove the empty basic block.  */
-  edge edge_to_remove;
+  edge edge_to_remove = NULL, keep_edge = NULL;
   if (EDGE_SUCC (cond_block, 0)->dest == bb)
-    edge_to_remove = EDGE_SUCC (cond_block, 1);
+    {
+      edge_to_remove = EDGE_SUCC (cond_block, 1);
+      keep_edge = EDGE_SUCC (cond_block, 0);
+    }
+  else if (EDGE_SUCC (cond_block, 1)->dest == bb)
+    {
+      edge_to_remove = EDGE_SUCC (cond_block, 0);
+      keep_edge = EDGE_SUCC (cond_block, 1);
+    }
+  else if ((keep_edge = find_edge (cond_block, e->src)))
+    ;
   else
-    edge_to_remove = EDGE_SUCC (cond_block, 0);
-  if (EDGE_COUNT (edge_to_remove->dest->preds) == 1)
+    gcc_unreachable ();
+
+  if (edge_to_remove && EDGE_COUNT (edge_to_remove->dest->preds) == 1)
     {
       e->flags |= EDGE_FALLTHRU;
       e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
@@ -444,9 +469,9 @@ replace_phi_edge_with_variable (basic_block cond_block,
 	 CFG cleanup deal with the edge removal to avoid
 	 updating dominators here in a non-trivial way.  */
       gcond *cond = as_a <gcond *> (last_stmt (cond_block));
-      if (edge_to_remove->flags & EDGE_TRUE_VALUE)
+      if (keep_edge->flags & EDGE_FALSE_VALUE)
 	gimple_cond_make_false (cond);
-      else
+      else if (keep_edge->flags & EDGE_TRUE_VALUE)
 	gimple_cond_make_true (cond);
     }
 
@@ -1733,15 +1758,52 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
   return 0;
 }
 
+/* If VAR is an SSA_NAME that points to a BIT_NOT_EXPR then return the TREE for
+   the value being inverted.  */
+
+static tree
+strip_bit_not (tree var)
+{
+  if (TREE_CODE (var) != SSA_NAME)
+    return NULL_TREE;
+
+  gimple *assign = SSA_NAME_DEF_STMT (var);
+  if (gimple_code (assign) != GIMPLE_ASSIGN)
+    return NULL_TREE;
+
+  if (gimple_assign_rhs_code (assign) != BIT_NOT_EXPR)
+    return NULL_TREE;
+
+  return gimple_assign_rhs1 (assign);
+}
+
+/* Invert a MIN to a MAX or a MAX to a MIN expression CODE.  */
+
+enum tree_code
+invert_minmax_code (enum tree_code code)
+{
+  switch (code) {
+  case MIN_EXPR:
+    return MAX_EXPR;
+  case MAX_EXPR:
+    return MIN_EXPR;
+  default:
+    gcc_unreachable ();
+  }
+}
+
 /*  The function minmax_replacement does the main work of doing the minmax
     replacement.  Return true if the replacement is done.  Otherwise return
     false.
     BB is the basic block where the replacement is going to be done on.  ARG0
-    is argument 0 from the PHI.  Likewise for ARG1.  */
+    is argument 0 from the PHI.  Likewise for ARG1.
+
+    If THREEWAY_P then expect the BB to be laid out in diamond shape with each
+    BB containing only a MIN or MAX expression.  */
 
 static bool
-minmax_replacement (basic_block cond_bb, basic_block middle_bb,
-		    edge e0, edge e1, gphi *phi, tree arg0, tree arg1)
+minmax_replacement (basic_block cond_bb, basic_block middle_bb, basic_block alt_middle_bb,
+		    edge e0, edge e1, gphi *phi, tree arg0, tree arg1, bool threeway_p)
 {
   tree result;
   edge true_edge, false_edge;
@@ -1896,16 +1958,20 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
   if (false_edge->dest == middle_bb)
     false_edge = EDGE_SUCC (false_edge->dest, 0);
 
+  /* When THREEWAY_P then e1 will point to the edge of the final transition
+     from middle-bb to end.  */
   if (true_edge == e0)
     {
-      gcc_assert (false_edge == e1);
+      if (!threeway_p)
+	gcc_assert (false_edge == e1);
       arg_true = arg0;
       arg_false = arg1;
     }
   else
     {
       gcc_assert (false_edge == e0);
-      gcc_assert (true_edge == e1);
+      if (!threeway_p)
+	gcc_assert (true_edge == e1);
       arg_true = arg1;
       arg_false = arg0;
     }
@@ -1937,6 +2003,165 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
       else
 	return false;
     }
+  else if (middle_bb != alt_middle_bb && threeway_p)
+    {
+      /* Recognize the following case:
+
+	 if (smaller < larger)
+	   a = MIN (smaller, c);
+	 else
+	   b = MIN (larger, c);
+	 x = PHI <a, b>
+
+	 This is equivalent to
+
+	 a = MIN (smaller, c);
+	 x = MIN (larger, a);  */
+
+      gimple *assign = last_and_only_stmt (middle_bb);
+      tree lhs, op0, op1, bound;
+      tree alt_lhs, alt_op0, alt_op1;
+      bool invert = false;
+
+      if (!single_pred_p (middle_bb)
+	  || !single_pred_p (alt_middle_bb)
+	  || !single_succ_p (middle_bb)
+	  || !single_succ_p (alt_middle_bb))
+	return false;
+
+      /* When THREEWAY_P then e1 will point to the edge of the final transition
+	 from middle-bb to end.  */
+      if (true_edge == e0)
+	gcc_assert (false_edge == EDGE_PRED (e1->src, 0));
+      else
+	gcc_assert (true_edge == EDGE_PRED (e1->src, 0));
+
+      bool valid_minmax_p = false;
+      gimple_stmt_iterator it1
+	= gsi_start_nondebug_after_labels_bb (middle_bb);
+      gimple_stmt_iterator it2
+	= gsi_start_nondebug_after_labels_bb (alt_middle_bb);
+      if (gsi_one_nondebug_before_end_p (it1)
+	  && gsi_one_nondebug_before_end_p (it2))
+	{
+	  gimple *stmt1 = gsi_stmt (it1);
+	  gimple *stmt2 = gsi_stmt (it2);
+	  if (is_gimple_assign (stmt1) && is_gimple_assign (stmt2))
+	    {
+	      enum tree_code code1 = gimple_assign_rhs_code (stmt1);
+	      enum tree_code code2 = gimple_assign_rhs_code (stmt2);
+	      valid_minmax_p = (code1 == MIN_EXPR || code1 == MAX_EXPR)
+			       && (code2 == MIN_EXPR || code2 == MAX_EXPR);
+	    }
+	}
+
+      if (!valid_minmax_p)
+	return false;
+
+      if (!assign
+	  || gimple_code (assign) != GIMPLE_ASSIGN)
+	return false;
+
+      lhs = gimple_assign_lhs (assign);
+      ass_code = gimple_assign_rhs_code (assign);
+      if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
+	return false;
+
+      op0 = gimple_assign_rhs1 (assign);
+      op1 = gimple_assign_rhs2 (assign);
+
+      assign = last_and_only_stmt (alt_middle_bb);
+      if (!assign
+	  || gimple_code (assign) != GIMPLE_ASSIGN)
+	return false;
+
+      alt_lhs = gimple_assign_lhs (assign);
+      if (ass_code != gimple_assign_rhs_code (assign))
+	return false;
+
+      if (!operand_equal_for_phi_arg_p (lhs, arg_true)
+	 || !operand_equal_for_phi_arg_p (alt_lhs, arg_false))
+	return false;
+
+      alt_op0 = gimple_assign_rhs1 (assign);
+      alt_op1 = gimple_assign_rhs2 (assign);
+
+      if ((operand_equal_for_phi_arg_p (op0, smaller)
+		|| (alt_smaller
+		    && operand_equal_for_phi_arg_p (op0, alt_smaller)))
+	       && (operand_equal_for_phi_arg_p (alt_op0, larger)
+		   || (alt_larger
+		       && operand_equal_for_phi_arg_p (alt_op0, alt_larger))))
+	{
+	  /* We got here if the condition is true, i.e., SMALLER < LARGER.  */
+	  if (!operand_equal_for_phi_arg_p (op1, alt_op1))
+	    return false;
+
+	  if ((arg0 = strip_bit_not (op0)) != NULL
+	      && (arg1 = strip_bit_not (alt_op0)) != NULL
+	      && (bound = strip_bit_not (op1)) != NULL)
+	    {
+	      minmax = MAX_EXPR;
+	      ass_code = invert_minmax_code (ass_code);
+	      invert = true;
+	    }
+	  else
+	    {
+	      bound = op1;
+	      minmax = MIN_EXPR;
+	      arg0 = op0;
+	      arg1 = alt_op0;
+	     }
+	}
+      else if ((operand_equal_for_phi_arg_p (op0, larger)
+		|| (alt_larger
+		    && operand_equal_for_phi_arg_p (op0, alt_larger)))
+	       && (operand_equal_for_phi_arg_p (alt_op0, smaller)
+		   || (alt_smaller
+		       && operand_equal_for_phi_arg_p (alt_op0, alt_smaller))))
+	{
+	  /* We got here if the condition is true, i.e., SMALLER > LARGER.  */
+	  if (!operand_equal_for_phi_arg_p (op1, alt_op1))
+	    return false;
+
+	  if ((arg0 = strip_bit_not (op0)) != NULL
+	      && (arg1 = strip_bit_not (alt_op0)) != NULL
+	      && (bound = strip_bit_not (op1)) != NULL)
+	    {
+	      minmax = MIN_EXPR;
+	      ass_code = invert_minmax_code (ass_code);
+	      invert = true;
+	    }
+	  else
+	    {
+	      bound = op1;
+	      minmax = MAX_EXPR;
+	      arg0 = op0;
+	      arg1 = alt_op0;
+	     }
+	}
+      else
+	return false;
+
+      /* Emit the statement to compute min/max.  */
+      location_t locus = gimple_location (last_stmt (cond_bb));
+      gimple_seq stmts = NULL;
+      tree phi_result = PHI_RESULT (phi);
+      result = gimple_build (&stmts, locus, minmax, TREE_TYPE (phi_result),
+			     arg0, bound);
+      result = gimple_build (&stmts, locus, ass_code, TREE_TYPE (phi_result),
+			     result, arg1);
+      if (invert)
+	result = gimple_build (&stmts, locus, BIT_NOT_EXPR, TREE_TYPE (phi_result),
+			       result);
+
+      gsi = gsi_last_bb (cond_bb);
+      gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT);
+
+      replace_phi_edge_with_variable (cond_bb, e1, phi, result);
+
+      return true;
+    }
   else
     {
       /* Recognize the following case, assuming d <= u:
</cut>
>From hjl@sc.intel.com  Thu Aug  4 08:27:50 2022
Return-Path: <hjl@sc.intel.com>
X-Original-To: gcc-regression@gcc.gnu.org
Delivered-To: gcc-regression@gcc.gnu.org
Received: from mga04.intel.com (mga04.intel.com [192.55.52.120])
 by sourceware.org (Postfix) with ESMTPS id 8C7C63857409
 for <gcc-regression@gcc.gnu.org>; Thu,  4 Aug 2022 08:27:49 +0000 (GMT)
DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8C7C63857409
X-IronPort-AV: E=McAfee;i="6400,9594,10428"; a="288633124"
X-IronPort-AV: E=Sophos;i="5.93,215,1654585200"; d="scan'208";a="288633124"
Received: from orsmga006.jf.intel.com ([10.7.209.51])
 by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;
 04 Aug 2022 01:27:44 -0700
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.93,215,1654585200"; d="scan'208";a="578986563"
Received: from scymds01.sc.intel.com ([10.148.94.138])
 by orsmga006.jf.intel.com with ESMTP; 04 Aug 2022 01:27:43 -0700
Received: from gnu-hsw-1.sc.intel.com (gnu-hsw-1.sc.intel.com [172.25.70.172])
 by scymds01.sc.intel.com with ESMTP id 2747XsSG015219;
 Thu, 4 Aug 2022 00:33:54 -0700
Received: by gnu-hsw-1.sc.intel.com (Postfix, from userid 1000)
 id 78B95400025; Thu,  4 Aug 2022 00:33:54 -0700 (PDT)
Date: Thu, 04 Aug 2022 00:33:54 -0700
To: skpgkp2@gmail.com, hjl.tools@gmail.com, gcc-regression@gcc.gnu.org
Subject: Regressions on master at commit r13-1954 vs commit r13-1941 on
 Linux/i686
User-Agent: Heirloom mailx 12.5 7/5/10
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-Id: <20220804073354.78B95400025@gnu-hsw-1.sc.intel.com>
From: "H.J. Lu" <hjl@sc.intel.com>
X-Spam-Status: No, score=-3458.9 required=5.0 tests=BAYES_00, KAM_DMARC_STATUS,
 KAM_LAZY_DOMAIN_SECURITY, KAM_NUMSUBJECT, SPF_HELO_NONE, SPF_NONE,
 TXREP autolearn=no autolearn_force=no version=3.4.6
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on
 server2.sourceware.org
X-BeenThere: gcc-regression@gcc.gnu.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Gcc-regression mailing list <gcc-regression.gcc.gnu.org>
List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-regression>,
 <mailto:gcc-regression-request@gcc.gnu.org?subject=unsubscribe>
List-Archive: <https://gcc.gnu.org/pipermail/gcc-regression/>
List-Post: <mailto:gcc-regression@gcc.gnu.org>
List-Help: <mailto:gcc-regression-request@gcc.gnu.org?subject=help>
List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-regression>,
 <mailto:gcc-regression-request@gcc.gnu.org?subject=subscribe>
X-List-Received-Date: Thu, 04 Aug 2022 08:27:50 -0000

New failures:
FAIL: gcc.dg/analyzer/pr96653.c (internal compiler error: in gimple_phi_arg, at gimple.h:4594)
FAIL: gcc.dg/analyzer/pr96653.c (test for excess errors)
FAIL: g++.dg/warn/uninit-pr105562.C  -std=gnu++14 (internal compiler error: in gimple_phi_arg, at gimple.h:4594)
FAIL: g++.dg/warn/uninit-pr105562.C  -std=gnu++14 (test for excess errors)
FAIL: g++.dg/warn/uninit-pr105562.C  -std=gnu++17 (internal compiler error: in gimple_phi_arg, at gimple.h:4594)
FAIL: g++.dg/warn/uninit-pr105562.C  -std=gnu++17 (test for excess errors)
FAIL: g++.dg/warn/uninit-pr105562.C  -std=gnu++20 (internal compiler error: in gimple_phi_arg, at gimple.h:4594)
FAIL: g++.dg/warn/uninit-pr105562.C  -std=gnu++20 (test for excess errors)
FAIL: gfortran.dg/make_unit.f90   -O1  (internal compiler error: in gimple_phi_arg, at gimple.h:4594)
FAIL: gfortran.dg/make_unit.f90   -O1  (test for excess errors)

New passes:


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-08-04  5:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-04  5:34 [TCWG CI] Regression caused by gcc: middle-end: Support recognition of three-way max/min ci_notify

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).