[gcc r15-3540] phiopt: Small refactoring/cleanup of non-ssa name case of factor_out_conditional_operation

2024-09-09 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:d1b3d099dd5789e3e7943ed23a9cd8c6c9689b2b

commit r15-3540-gd1b3d099dd5789e3e7943ed23a9cd8c6c9689b2b
Author: Andrew Pinski 
Date:   Sat Aug 31 13:54:21 2024 -0700

phiopt: Small refactoring/cleanup of non-ssa name case of 
factor_out_conditional_operation

This small cleanup removes a redundant check for gimple_assign_cast_p and 
reformats
based on that. Also changes the if statement that checks if the integral 
type and the
check to see if the constant fits into the new type such that it returns 
null
and reformats based on that.

Also moves the check for has_single_use earlier so it is less complex still 
a cheaper
check than some of the others (like the check on the integer side).

This was noticed when adding a few new things to 
factor_out_conditional_operation
but those are not ready to submit yet.

Note there are no functional difference with this change.

Bootstrapped and tested on x86_64-linux-gnu.

gcc/ChangeLog:

* tree-ssa-phiopt.cc (factor_out_conditional_operation): Move the 
has_single_use
checks much earlier. Remove redundant check for 
gimple_assign_cast_p.
Change around the check if the integral consts fits into the new 
type.

Signed-off-by: Andrew Pinski 

Diff:
---
 gcc/tree-ssa-phiopt.cc | 122 -
 1 file changed, 60 insertions(+), 62 deletions(-)

diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 271a5d51f09f..06ec5875722b 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -265,6 +265,11 @@ factor_out_conditional_operation (edge e0, edge e1, gphi 
*phi,
   tree new_arg0 = arg0_op.ops[0];
   tree new_arg1;
 
+  /* If arg0 have > 1 use, then this transformation actually increases
+ the number of expressions evaluated at runtime.  */
+  if (!has_single_use (arg0))
+return NULL;
+
   if (TREE_CODE (arg1) == SSA_NAME)
 {
   /* Check if arg1 is an SSA_NAME.  */
@@ -278,6 +283,11 @@ factor_out_conditional_operation (edge e0, edge e1, gphi 
*phi,
   if (arg1_op.operands_occurs_in_abnormal_phi ())
return NULL;
 
+  /* If arg1 have > 1 use, then this transformation actually increases
+the number of expressions evaluated at runtime.  */
+  if (!has_single_use (arg1))
+   return NULL;
+
   /* Either arg1_def_stmt or arg0_def_stmt should be conditional.  */
   if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb 
(arg0_def_stmt))
  && dominated_by_p (CDI_DOMINATORS,
@@ -295,80 +305,68 @@ factor_out_conditional_operation (edge e0, edge e1, gphi 
*phi,
   if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb 
(arg0_def_stmt)))
return NULL;
 
-  /* If arg1 is an INTEGER_CST, fold it to new type.  */
-  if (INTEGRAL_TYPE_P (TREE_TYPE (new_arg0))
- && (int_fits_type_p (arg1, TREE_TYPE (new_arg0))
- || (TYPE_PRECISION (TREE_TYPE (new_arg0))
+  /* Only handle if arg1 is a INTEGER_CST and one that fits
+into the new type or if it is the same precision.  */
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (new_arg0))
+ || !(int_fits_type_p (arg1, TREE_TYPE (new_arg0))
+  || (TYPE_PRECISION (TREE_TYPE (new_arg0))
   == TYPE_PRECISION (TREE_TYPE (arg1)
+   return NULL;
+
+  /* For the INTEGER_CST case, we are just moving the
+conversion from one place to another, which can often
+hurt as the conversion moves further away from the
+statement that computes the value.  So, perform this
+only if new_arg0 is an operand of COND_STMT, or
+if arg0_def_stmt is the only non-debug stmt in
+its basic block, because then it is possible this
+could enable further optimizations (minmax replacement
+etc.).  See PR71016.
+Note no-op conversions don't have this issue as
+it will not generate any zero/sign extend in that case.  */
+  if ((TYPE_PRECISION (TREE_TYPE (new_arg0))
+  != TYPE_PRECISION (TREE_TYPE (arg1)))
+ && new_arg0 != gimple_cond_lhs (cond_stmt)
+ && new_arg0 != gimple_cond_rhs (cond_stmt)
+ && gimple_bb (arg0_def_stmt) == e0->src)
{
- if (gimple_assign_cast_p (arg0_def_stmt))
+ gsi = gsi_for_stmt (arg0_def_stmt);
+ gsi_prev_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
{
- /* For the INTEGER_CST case, we are just moving the
-conversion from one place to another, which can often
-hurt as the conversion moves further away from the
-statement that computes the value.  So, perform this
-only if new_arg0 is an operand of COND_STMT, or
-if arg0_def_stmt is the only non-debug stmt in
-its basic block, because then it is possible this
-could enable f

[gcc r15-3541] Match: Fix ordered and nonequal: Fix 'gcc.dg/opt-ordered-and-nonequal-1.c' re 'LOGICAL_OP_NON_SHORT_

2024-09-09 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:00b35424cbdd0985e87e6de2c381ee3c3f7fdc21

commit r15-3541-g00b35424cbdd0985e87e6de2c381ee3c3f7fdc21
Author: Thomas Schwinge 
Date:   Mon Sep 9 08:39:10 2024 +0200

Match: Fix ordered and nonequal: Fix 'gcc.dg/opt-ordered-and-nonequal-1.c' 
re 'LOGICAL_OP_NON_SHORT_CIRCUIT' [PR116635]

Fix up to make 'gcc.dg/opt-ordered-and-nonequal-1.c' of
commit 91421e21e8f0f05f440174b8de7a43a311700e08
"Match: Fix ordered and nonequal" work for default
'LOGICAL_OP_NON_SHORT_CIRCUIT == false' configurations.

PR testsuite/116635
gcc/testsuite/
* gcc.dg/opt-ordered-and-nonequal-1.c: Fix re
'LOGICAL_OP_NON_SHORT_CIRCUIT'.

Diff:
---
 gcc/testsuite/gcc.dg/opt-ordered-and-nonequal-1.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/opt-ordered-and-nonequal-1.c 
b/gcc/testsuite/gcc.dg/opt-ordered-and-nonequal-1.c
index 6d102c2bd0c8..d61c3322214b 100644
--- a/gcc/testsuite/gcc.dg/opt-ordered-and-nonequal-1.c
+++ b/gcc/testsuite/gcc.dg/opt-ordered-and-nonequal-1.c
@@ -1,5 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -fdump-tree-forwprop1-details" } */
+/* Make this work for default 'LOGICAL_OP_NON_SHORT_CIRCUIT == false' 
configurations:
+   { dg-additional-options "--param logical-op-non-short-circuit=1" } */
 
 int is_ordered_and_nonequal_sh_1 (float a, float b)
 {


[gcc r15-3542] testsuite: Fix up pr116588.c test [PR116588]

2024-09-09 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:765875e2c18b8f4c346b754a19e287efaec531a5

commit r15-3542-g765875e2c18b8f4c346b754a19e287efaec531a5
Author: Jakub Jelinek 
Date:   Mon Sep 9 09:37:26 2024 +0200

testsuite: Fix up pr116588.c test [PR116588]

The test as committed without the tree-vrp.cc change only FAILs with
FAIL: gcc.dg/pr116588.c scan-tree-dump-not vrp2 "0 != 0"
The DEBUG code in there was just to make it easier to debug, but doesn't
actually fail when the test is miscompiled.
We don't need such debugging code in simple tests like that, but it is
useful if they abort when miscompiled.

With this patch without the tree-vrp.cc change I see
FAIL: gcc.dg/pr116588.c execution test
FAIL: gcc.dg/pr116588.c scan-tree-dump-not vrp2 "0 != 0"
and with it it passes.

2024-09-09  Jakub Jelinek  

PR tree-optimization/116588
* gcc.dg/pr116588.c: Remove -DDEBUG from dg-options.
(main): Remove debugging code and simplify.

Diff:
---
 gcc/testsuite/gcc.dg/pr116588.c | 13 +++--
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/pr116588.c b/gcc/testsuite/gcc.dg/pr116588.c
index 6b0678d465ed..481772a54e15 100644
--- a/gcc/testsuite/gcc.dg/pr116588.c
+++ b/gcc/testsuite/gcc.dg/pr116588.c
@@ -1,7 +1,7 @@
 /* PR tree-optimization/116588 */
 /* { dg-do run { target bitint575 } } */
 /* { dg-require-effective-target int128 } */
-/* { dg-options "-O2 -fno-vect-cost-model -fno-tree-dominator-opts 
-fno-tree-fre --param=vrp-block-limit=0  -DDEBUG -fdump-tree-vrp2-details" } */
+/* { dg-options "-O2 -fno-vect-cost-model -fno-tree-dominator-opts 
-fno-tree-fre --param=vrp-block-limit=0 -fdump-tree-vrp2-details" } */
 
 int a;
 __int128 b, c;
@@ -18,15 +18,8 @@ foo (_BitInt (129) e)
 int
 main ()
 {
-  __int128 x = foo (0);
-#ifdef DEBUG
-  for (unsigned i = 0; i < sizeof (x); i++)
-__builtin_printf ("%02x", i[(volatile unsigned char *) &x]);
-  __builtin_printf("\n");
-#else
-  if (x)
-__builtin_abort();
-#endif
+  if (foo (0))
+__builtin_abort ();
 }
 
 /* { dg-final { scan-tree-dump-not "0 != 0" "vrp2" } } */


[gcc r15-3543] Amend gcc.dg/vect/fast-math-vect-call-2.c

2024-09-09 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:924855daa204b4821057313cad44898445824e11

commit r15-3543-g924855daa204b4821057313cad44898445824e11
Author: Richard Biener 
Date:   Mon Sep 9 09:41:36 2024 +0200

Amend gcc.dg/vect/fast-math-vect-call-2.c

There was a reported regression on x86-64 with -march=cascadelake
and -m32 where epilogue vectorization causes a different number of
SLPed loops.  Fixed by disabling epilogue vectorization for the
testcase.

* gcc.dg/vect/fast-math-vect-call-2.c: Disable epilogue
vectorization.

Diff:
---
 gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c 
b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c
index ed42a21cedc1..e52ffe435d33 100644
--- a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c
+++ b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c
@@ -1,4 +1,5 @@
 /* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "--param vect-epilogues-nomask=0" } */
 
 #include "tree-vect.h"


[gcc r15-3544] gimple-fold: Move optimizing memcpy to memset to fold_stmt from fab

2024-09-09 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:2067df800df930dd13aa20a826373bb27cfdd420

commit r15-3544-g2067df800df930dd13aa20a826373bb27cfdd420
Author: Andrew Pinski 
Date:   Fri Sep 6 12:29:26 2024 -0700

gimple-fold: Move optimizing memcpy to memset to fold_stmt from fab

I noticed this folding inside fab could be done else where and could
even improve inlining decisions and a few other things so let's
move it to fold_stmt.
It also fixes PR 116601 because places which call fold_stmt already
have to deal with the stmt becoming a non-throw statement.

For the fix for PR 116601 on the branches should be the original patch
rather than a backport of this one.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/116601

gcc/ChangeLog:

* gimple-fold.cc (optimize_memcpy_to_memset): Move
from tree-ssa-ccp.cc and rename. Also return true
if the optimization happened.
(gimple_fold_builtin_memory_op): Call
optimize_memcpy_to_memset.
(fold_stmt_1): Call optimize_memcpy_to_memset for
load/store copies.
* tree-ssa-ccp.cc (optimize_memcpy): Delete.
(pass_fold_builtins::execute): Remove code that
calls optimize_memcpy.

gcc/testsuite/ChangeLog:

* gcc.dg/pr78408-1.c: Adjust dump scan to match where
the optimization now happens.
* g++.dg/torture/except-2.C: New test.

Signed-off-by: Andrew Pinski 

Diff:
---
 gcc/gimple-fold.cc  | 134 
 gcc/testsuite/g++.dg/torture/except-2.C |  18 +
 gcc/testsuite/gcc.dg/pr78408-1.c|   5 +-
 gcc/tree-ssa-ccp.cc | 132 +--
 4 files changed, 156 insertions(+), 133 deletions(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 2746fcfe314f..942de7720fd2 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -894,6 +894,121 @@ size_must_be_zero_p (tree size)
   return vr.zero_p ();
 }
 
+/* Optimize
+   a = {};
+   b = a;
+   into
+   a = {};
+   b = {};
+   Similarly for memset (&a, ..., sizeof (a)); instead of a = {};
+   and/or memcpy (&b, &a, sizeof (a)); instead of b = a;  */
+
+static bool
+optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, 
tree len)
+{
+  gimple *stmt = gsi_stmt (*gsip);
+  if (gimple_has_volatile_ops (stmt))
+return false;
+
+  tree vuse = gimple_vuse (stmt);
+  if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME)
+return false;
+
+  gimple *defstmt = SSA_NAME_DEF_STMT (vuse);
+  tree src2 = NULL_TREE, len2 = NULL_TREE;
+  poly_int64 offset, offset2;
+  tree val = integer_zero_node;
+  if (gimple_store_p (defstmt)
+  && gimple_assign_single_p (defstmt)
+  && TREE_CODE (gimple_assign_rhs1 (defstmt)) == CONSTRUCTOR
+  && !gimple_clobber_p (defstmt))
+src2 = gimple_assign_lhs (defstmt);
+  else if (gimple_call_builtin_p (defstmt, BUILT_IN_MEMSET)
+  && TREE_CODE (gimple_call_arg (defstmt, 0)) == ADDR_EXPR
+  && TREE_CODE (gimple_call_arg (defstmt, 1)) == INTEGER_CST)
+{
+  src2 = TREE_OPERAND (gimple_call_arg (defstmt, 0), 0);
+  len2 = gimple_call_arg (defstmt, 2);
+  val = gimple_call_arg (defstmt, 1);
+  /* For non-0 val, we'd have to transform stmt from assignment
+into memset (only if dest is addressable).  */
+  if (!integer_zerop (val) && is_gimple_assign (stmt))
+   src2 = NULL_TREE;
+}
+
+  if (src2 == NULL_TREE)
+return false;
+
+  if (len == NULL_TREE)
+len = (TREE_CODE (src) == COMPONENT_REF
+  ? DECL_SIZE_UNIT (TREE_OPERAND (src, 1))
+  : TYPE_SIZE_UNIT (TREE_TYPE (src)));
+  if (len2 == NULL_TREE)
+len2 = (TREE_CODE (src2) == COMPONENT_REF
+   ? DECL_SIZE_UNIT (TREE_OPERAND (src2, 1))
+   : TYPE_SIZE_UNIT (TREE_TYPE (src2)));
+  if (len == NULL_TREE
+  || !poly_int_tree_p (len)
+  || len2 == NULL_TREE
+  || !poly_int_tree_p (len2))
+return false;
+
+  src = get_addr_base_and_unit_offset (src, &offset);
+  src2 = get_addr_base_and_unit_offset (src2, &offset2);
+  if (src == NULL_TREE
+  || src2 == NULL_TREE
+  || maybe_lt (offset, offset2))
+return false;
+
+  if (!operand_equal_p (src, src2, 0))
+return false;
+
+  /* [ src + offset2, src + offset2 + len2 - 1 ] is set to val.
+ Make sure that
+ [ src + offset, src + offset + len - 1 ] is a subset of that.  */
+  if (maybe_gt (wi::to_poly_offset (len) + (offset - offset2),
+   wi::to_poly_offset (len2)))
+return false;
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+{
+  fprintf (dump_file, "Simplified\n  ");
+  print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+  fprintf (dump_file, "after previous\n  ");
+  print_gimple_stmt (dump_file, defstmt, 0, dump_flags);
+}
+
+  /* For simplicity, don't change the kind of 

[gcc r15-3545] Remove problematic declaration for 32-bit targets

2024-09-09 Thread Eric Botcazou via Gcc-cvs
https://gcc.gnu.org/g:4645aa79a6dfe39cb58d21ee251bfde59a6b27d4

commit r15-3545-g4645aa79a6dfe39cb58d21ee251bfde59a6b27d4
Author: Eric Botcazou 
Date:   Mon Sep 9 12:23:42 2024 +0200

Remove problematic declaration for 32-bit targets

gcc/testsuite
PR ada/115246
* gnat.dg/alignment14.adb (My_Int2): Delete.
(Arr2): Likewise.

Diff:
---
 gcc/testsuite/gnat.dg/alignment14.adb | 5 -
 1 file changed, 5 deletions(-)

diff --git a/gcc/testsuite/gnat.dg/alignment14.adb 
b/gcc/testsuite/gnat.dg/alignment14.adb
index 48ef6bd14e60..a5890a91148e 100644
--- a/gcc/testsuite/gnat.dg/alignment14.adb
+++ b/gcc/testsuite/gnat.dg/alignment14.adb
@@ -7,11 +7,6 @@ procedure Alignment14 is
 
   type Arr1 is array (1 .. 2) of My_Int1;
 
-  type My_Int2 is new Integer;
-  for My_Int2'Alignment use 16;
-
-  type Arr2 is array (1 .. 2) of My_Int2;
-
 begin
null;
 end Alignment14;


[gcc r15-3546] Silence warning for 32-bit targets

2024-09-09 Thread Eric Botcazou via Gcc-cvs
https://gcc.gnu.org/g:0171793aca4c0d4e9c8020c539bb4d3abfb91da7

commit r15-3546-g0171793aca4c0d4e9c8020c539bb4d3abfb91da7
Author: Eric Botcazou 
Date:   Mon Sep 9 12:27:25 2024 +0200

Silence warning for 32-bit targets

gcc/testsuite
PR ada/115250
* gnat.dg/opt58_pkg.ads: Convert to Unix line ending.
* gnat.dg/opt58.adb: Likewise and pass -gnatws to the compiler.

Diff:
---
 gcc/testsuite/gnat.dg/opt58.adb | 38 ++---
 gcc/testsuite/gnat.dg/opt58_pkg.ads | 38 ++---
 2 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/gcc/testsuite/gnat.dg/opt58.adb b/gcc/testsuite/gnat.dg/opt58.adb
index ac39cc06056e..16326ae615f2 100644
--- a/gcc/testsuite/gnat.dg/opt58.adb
+++ b/gcc/testsuite/gnat.dg/opt58.adb
@@ -1,19 +1,19 @@
--- { dg-do compile }
--- { dg-options "-O" }
-
-with Unchecked_Conversion;
-with System; use System;
-with Opt58_Pkg; use Opt58_Pkg;
-
-procedure Opt58 is
-
-   function Convert is new Unchecked_Conversion (Integer, Rec);
-
-   Dword : Integer := 0;
-   I : Small_Int := F1 (Convert (Dword));
-
-begin
-   if F2 (Null_Address, I = 0) then
-  null;
-   end if;
-end Opt58;
+-- { dg-do compile }
+-- { dg-options "-O -gnatws" }
+
+with Unchecked_Conversion;
+with System; use System;
+with Opt58_Pkg; use Opt58_Pkg;
+
+procedure Opt58 is
+
+   function Convert is new Unchecked_Conversion (Integer, Rec);
+
+   Dword : Integer := 0;
+   I : Small_Int := F1 (Convert (Dword));
+
+begin
+   if F2 (Null_Address, I = 0) then
+  null;
+   end if;
+end Opt58;
diff --git a/gcc/testsuite/gnat.dg/opt58_pkg.ads 
b/gcc/testsuite/gnat.dg/opt58_pkg.ads
index 9cb7f3a2540f..02a374fd1e95 100644
--- a/gcc/testsuite/gnat.dg/opt58_pkg.ads
+++ b/gcc/testsuite/gnat.dg/opt58_pkg.ads
@@ -1,19 +1,19 @@
-with System; use System;
-
-package Opt58_Pkg is
-
-   pragma Pure (Opt58_Pkg);
-
-   type Small_Int is range 0 .. 255;
-
-   type Rec is record
- D1, D2, D3, D4 : Small_Int;
-   end record;
-   pragma Pack (Rec);
-   for Rec'Size use 32;
-
-   function F1 (R : Rec) return Small_Int;
-
-   function F2 (A : Address; B : Boolean) return Boolean;
-
-end Opt58_Pkg;
+with System; use System;
+
+package Opt58_Pkg is
+
+   pragma Pure (Opt58_Pkg);
+
+   type Small_Int is range 0 .. 255;
+
+   type Rec is record
+ D1, D2, D3, D4 : Small_Int;
+   end record;
+   pragma Pack (Rec);
+   for Rec'Size use 32;
+
+   function F1 (R : Rec) return Small_Int;
+
+   function F2 (A : Address; B : Boolean) return Boolean;
+
+end Opt58_Pkg;


[gcc r15-3547] tree-optimization/116647 - wrong classified double reduction

2024-09-09 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:898e3e95a6acf542baf03be95ce5bf7b3ad04276

commit r15-3547-g898e3e95a6acf542baf03be95ce5bf7b3ad04276
Author: Richard Biener 
Date:   Mon Sep 9 11:51:24 2024 +0200

tree-optimization/116647 - wrong classified double reduction

The following avoids classifying a double reduction that's not
actually a reduction in the outer loop (because its value isn't
used outside of the outer loop).  This avoids us ICEing on the
unexpected stmt/SLP node arrangement.

PR tree-optimization/116647
* tree-vect-loop.cc (vect_is_simple_reduction): Add missing
check to double reduction detection.

* gcc.dg/torture/pr116647.c: New testcase.
* gcc.dg/vect/no-scevccp-pr86725-2.c: Adjust expected pattern.
* gcc.dg/vect/no-scevccp-pr86725-4.c: Likewise.

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr116647.c  | 22 ++
 gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c |  2 +-
 gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c |  2 +-
 gcc/tree-vect-loop.cc|  3 ++-
 4 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr116647.c 
b/gcc/testsuite/gcc.dg/torture/pr116647.c
new file mode 100644
index ..2b5cc3486900
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116647.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+int a;
+char b;
+long c, d, e;
+unsigned long f;
+long g() {
+  if (a <= 0)
+return 1;
+  for (; d; d++) {
+e = 0;
+for (; e < a; e++) {
+  unsigned long h = 0;
+  switch (b)
+  case 2:
+if (e)
+  h = 5;
+  c += h;
+}
+  }
+  c /= f;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c 
b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c
index b208c1a2d615..66185a9483ba 100644
--- a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c
@@ -19,5 +19,5 @@ nr (int xe)
   return xe;
 }
 
-/* { dg-final { scan-tree-dump "reduction used in loop" "vect" { target 
vect_int } } } */
+/* { dg-final { scan-tree-dump "Unknown def-use cycle pattern" "vect" { target 
vect_int } } } */
 /* { dg-final { scan-tree-dump-not "OUTER LOOP VECTORIZED" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c 
b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c
index d995c9b30fe2..6ada0a10cb36 100644
--- a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c
@@ -19,5 +19,5 @@ nr (unsigned int xe, unsigned int qqn)
   return xe;
 }
 
-/* { dg-final { scan-tree-dump "reduction used in loop" "vect" { target 
vect_int } } } */
+/* { dg-final { scan-tree-dump "Unknown def-use cycle pattern" "vect" { target 
vect_int } } } */
 /* { dg-final { scan-tree-dump-not "OUTER LOOP VECTORIZED" "vect" } } */
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index a879a13bbf0c..65d7ed51067e 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -4325,7 +4325,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, 
stmt_vec_info phi_info,
  && is_a  (phi_use_stmt)
  && flow_bb_inside_loop_p (loop->inner, gimple_bb (phi_use_stmt))
  && (op1 == PHI_ARG_DEF_FROM_EDGE (phi_use_stmt,
-   loop_latch_edge (loop->inner
+   loop_latch_edge (loop->inner)))
+ && lcphis.length () == 1)
 {
   if (dump_enabled_p ())
 report_vect_op (MSG_NOTE, def_stmt,


[gcc r15-3548] tree-optimization/116514 - handle pointer difference in bit-CCP

2024-09-09 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:e7d5b9aa021f6fc32810670b18ffabe543262775

commit r15-3548-ge7d5b9aa021f6fc32810670b18ffabe543262775
Author: Richard Biener 
Date:   Wed Aug 28 14:06:48 2024 +0200

tree-optimization/116514 - handle pointer difference in bit-CCP

When evaluating the difference of two aligned pointers in CCP we
fail to handle the EXACT_DIV_EXPR by the element size that occurs.
The testcase then also exercises modulo to test alignment but
modulo by a power-of-two isn't handled either.

PR tree-optimization/116514
* tree-ssa-ccp.cc (bit_value_binop): Handle EXACT_DIV_EXPR
like TRUNC_DIV_EXPR.  Handle exact division of a signed value
by a power-of-two like a shift.  Handle unsigned division by
a power-of-two like a shift.
Handle unsigned TRUNC_MOD_EXPR by power-of-two, handle signed
TRUNC_MOD_EXPR by power-of-two if the result is zero.

* gcc.dg/tree-ssa/ssa-ccp-44.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-44.c | 13 +
 gcc/tree-ssa-ccp.cc| 27 ++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-44.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-44.c
new file mode 100644
index ..f1f09bfb1170
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-44.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ccp1" } */
+
+int
+test(int* a, int* b)
+{
+  __INTPTR_TYPE__ delta = (int*)__builtin_assume_aligned(b, 32)
+   - (int*)__builtin_assume_aligned(a, 32);
+  __INTPTR_TYPE__ x = delta % 8;
+  return (x == 0);
+}
+
+/* { dg-final { scan-tree-dump "return 1;" "ccp1" } } */
diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index 47b2ce9441e5..a5f6ef5f5ddd 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -1921,6 +1921,27 @@ bit_value_binop (enum tree_code code, signop sgn, int 
width,
   {
widest_int r1max = r1val | r1mask;
widest_int r2max = r2val | r2mask;
+   if (r2mask == 0)
+ {
+   widest_int shift = wi::exact_log2 (r2val);
+   if (shift != -1)
+ {
+   // Handle modulo by a power of 2 as a bitwise and.
+   widest_int tem_val, tem_mask;
+   bit_value_binop (BIT_AND_EXPR, sgn, width, &tem_val, &tem_mask,
+r1type_sgn, r1type_precision, r1val, r1mask,
+r2type_sgn, r2type_precision,
+r2val - 1, r2mask);
+   if (sgn == UNSIGNED
+   || !wi::neg_p (r1max)
+   || (tem_mask == 0 && tem_val == 0))
+ {
+   *val = tem_val;
+   *mask = tem_mask;
+   return;
+ }
+ }
+ }
if (sgn == UNSIGNED
|| (!wi::neg_p (r1max) && !wi::neg_p (r2max)))
  {
@@ -1949,11 +1970,15 @@ bit_value_binop (enum tree_code code, signop sgn, int 
width,
}
   break;
 
+case EXACT_DIV_EXPR:
 case TRUNC_DIV_EXPR:
   {
widest_int r1max = r1val | r1mask;
widest_int r2max = r2val | r2mask;
-   if (r2mask == 0 && !wi::neg_p (r1max))
+   if (r2mask == 0
+   && (code == EXACT_DIV_EXPR
+   || sgn == UNSIGNED
+   || !wi::neg_p (r1max)))
  {
widest_int shift = wi::exact_log2 (r2val);
if (shift != -1)


[gcc r15-3549] hppa: Don't canonicalize operand order of scaled index addresses

2024-09-09 Thread John David Anglin via Gcc-cvs
https://gcc.gnu.org/g:8f3b402b6fca3e4b018e99f65bf22f478e888c16

commit r15-3549-g8f3b402b6fca3e4b018e99f65bf22f478e888c16
Author: John David Anglin 
Date:   Mon Sep 9 10:23:00 2024 -0400

hppa: Don't canonicalize operand order of scaled index addresses

pa_print_operand handles both operand orders for scaled index
addresses, so it isn't necessary to canonicalize the order of
operands.

2024-09-09  John David Anglin  

gcc/ChangeLog:

* config/pa/pa.cc (pa_legitimate_address_p): Don't
canonicalize operand order of scaled index addresses.

Diff:
---
 gcc/config/pa/pa.cc | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc
index 631f18a0ef51..84aa4f1b1f2a 100644
--- a/gcc/config/pa/pa.cc
+++ b/gcc/config/pa/pa.cc
@@ -11022,14 +11022,13 @@ pa_legitimate_address_p (machine_mode mode, rtx x, 
bool strict, code_helper)
return true;
 
   if (!TARGET_DISABLE_INDEXING
- && GET_CODE (index) == MULT
  /* Only accept base operands with the REG_POINTER flag prior to
 reload on targets with non-equivalent space registers.  */
  && (TARGET_NO_SPACE_REGS
- || (base == XEXP (x, 1)
- && (reload_completed
- || (reload_in_progress && HARD_REGISTER_P (base))
- || REG_POINTER (base
+ || reload_completed
+ || (reload_in_progress && HARD_REGISTER_P (base))
+ || REG_POINTER (base))
+ && GET_CODE (index) == MULT
  && REG_P (XEXP (index, 0))
  && GET_MODE (XEXP (index, 0)) == Pmode
  && MODE_OK_FOR_SCALED_INDEXING_P (mode)


[gcc r15-3550] middle-end: also optimized `popcount(a) <= 1` [PR90693]

2024-09-09 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:75a4143d69a842d691c14a477b0ba277d8708fc7

commit r15-3550-g75a4143d69a842d691c14a477b0ba277d8708fc7
Author: Andrew Pinski 
Date:   Thu Aug 29 12:10:44 2024 -0700

middle-end: also optimized `popcount(a) <= 1` [PR90693]

This expands on optimizing `popcount(a) == 1` to also handle
`popcount(a) <= 1`. `<= 1` can be expanded as `(a & -a) == 0`
like what is done for `== 1` if we know that a was nonzero.
We have to do the optimization in 2 places due to if we have
an optab entry for popcount or not.

Built and tested for aarch64-linux-gnu.

PR middle-end/90693

gcc/ChangeLog:

* internal-fn.cc (expand_POPCOUNT): Handle the second argument
being `-1` for `<= 1`.
* tree-ssa-math-opts.cc (match_single_bit_test): Handle LE/GT
cases.
(math_opts_dom_walker::after_dom_children): Call 
match_single_bit_test
for LE_EXPR/GT_EXPR also.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/popcnt-le-1.c: New test.
* gcc.target/aarch64/popcnt-le-2.c: New test.
* gcc.target/aarch64/popcnt-le-3.c: New test.

Signed-off-by: Andrew Pinski 

Diff:
---
 gcc/internal-fn.cc | 20 -
 gcc/testsuite/gcc.target/aarch64/popcnt-le-1.c | 29 
 gcc/testsuite/gcc.target/aarch64/popcnt-le-2.c | 31 ++
 gcc/testsuite/gcc.target/aarch64/popcnt-le-3.c | 31 ++
 gcc/tree-ssa-math-opts.cc  | 25 -
 5 files changed, 129 insertions(+), 7 deletions(-)

diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 4e33db365ac9..b55f089cf56d 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -5304,11 +5304,16 @@ expand_POPCOUNT (internal_fn fn, gcall *stmt)
  Use rtx costs in that case to determine if .POPCOUNT (arg) == 1
  or (arg ^ (arg - 1)) > arg - 1 is cheaper.
  If .POPCOUNT second argument is 0, we additionally know that arg
- is non-zero, so use arg & (arg - 1) == 0 instead.  */
+ is non-zero, so use arg & (arg - 1) == 0 instead.
+ If .POPCOUNT second argument is -1, the comparison was either `<= 1`
+ or `> 1`.  */
   bool speed_p = optimize_insn_for_speed_p ();
   tree lhs = gimple_call_lhs (stmt);
   tree arg = gimple_call_arg (stmt, 0);
   bool nonzero_arg = integer_zerop (gimple_call_arg (stmt, 1));
+  bool was_le = integer_minus_onep (gimple_call_arg (stmt, 1));
+  if (was_le)
+nonzero_arg = true;
   tree type = TREE_TYPE (arg);
   machine_mode mode = TYPE_MODE (type);
   machine_mode lhsmode = TYPE_MODE (TREE_TYPE (lhs));
@@ -5360,10 +5365,23 @@ expand_POPCOUNT (internal_fn fn, gcall *stmt)
 emit_insn (popcount_insns);
   else
 {
+  start_sequence ();
   emit_insn (cmp_insns);
   plhs = expand_normal (lhs);
   if (GET_MODE (cmp) != GET_MODE (plhs))
cmp = convert_to_mode (GET_MODE (plhs), cmp, 1);
+  /* For `<= 1`, we need to produce `2 - cmp` or `cmp ? 1 : 2` as that
+then gets compared against 1 and we need the false case to be 2.  */
+  if (was_le)
+   {
+ cmp = expand_simple_binop (GET_MODE (cmp), MINUS, const2_rtx,
+cmp, NULL_RTX, 1, OPTAB_WIDEN);
+ if (!cmp)
+   goto fail;
+   }
   emit_move_insn (plhs, cmp);
+  rtx_insn *all_insns = get_insns ();
+  end_sequence ();
+  emit_insn (all_insns);
 }
 }
diff --git a/gcc/testsuite/gcc.target/aarch64/popcnt-le-1.c 
b/gcc/testsuite/gcc.target/aarch64/popcnt-le-1.c
new file mode 100644
index ..b4141da982c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/popcnt-le-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-expand-details" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* PR middle-end/90693 */
+
+#pragma GCC target "+nocssc"
+
+/*
+** le32:
+** sub w([0-9]+), w0, #1
+** tst w0, w\1
+** csetw0, eq
+** ret
+*/
+
+unsigned le32 (const unsigned int a) {
+  return __builtin_popcountg (a) <= 1;
+}
+
+/*
+** gt32:
+** sub w([0-9]+), w0, #1
+** tst w0, w\1
+** csetw0, ne
+** ret
+*/
+unsigned gt32 (const unsigned int a) {
+  return __builtin_popcountg (a) > 1;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/popcnt-le-2.c 
b/gcc/testsuite/gcc.target/aarch64/popcnt-le-2.c
new file mode 100644
index ..975552ca63e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/popcnt-le-2.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mgeneral-regs-only -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "POPCOUNT \\\(" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "__builtin_popcount \\\(" "optimized" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* PR middle-end/90693 */
+
+#pragma GCC target "+nocssc

[gcc r15-3551] analyzer: fix "unused variable 'summary_cast_reg'" warning

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:6e35b0e8572a71d0e6f407cc356592a0b97fc298

commit r15-3551-g6e35b0e8572a71d0e6f407cc356592a0b97fc298
Author: David Malcolm 
Date:   Mon Sep 9 15:30:42 2024 -0400

analyzer: fix "unused variable 'summary_cast_reg'" warning

I missed this in r15-1108-g70f26314b62e2d.

gcc/analyzer/ChangeLog:
* call-summary.cc
(call_summary_replay::convert_region_from_summary_1): Drop unused
local "summary_cast_reg"

Signed-off-by: David Malcolm 

Diff:
---
 gcc/analyzer/call-summary.cc | 2 --
 1 file changed, 2 deletions(-)

diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index ec36fdfd9f1a..663a89567a79 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -724,8 +724,6 @@ call_summary_replay::convert_region_from_summary_1 (const 
region *summary_reg)
   break;
 case RK_CAST:
   {
-   const cast_region *summary_cast_reg
- = as_a  (summary_reg);
const region *summary_parent_reg = summary_reg->get_parent_region ();
const region *caller_parent_reg
  = convert_region_from_summary (summary_parent_reg);


[gcc r15-3552] i386: Use offsetable address constraint for double-word memory operands

2024-09-09 Thread Uros Bizjak via Gcc-cvs
https://gcc.gnu.org/g:1da79de5275de82bc810d2f8d70fbc98dbce3da5

commit r15-3552-g1da79de5275de82bc810d2f8d70fbc98dbce3da5
Author: Uros Bizjak 
Date:   Mon Sep 9 22:33:52 2024 +0200

i386: Use offsetable address constraint for double-word memory operands

Double-word memory operands are accessed as their high and low part, so the
memory location has to be offsettable.  Use "o" constraint instead of "m"
for double-word memory operands.

gcc/ChangeLog:

* config/i386/i386.md (*insvdi_lowpart_1): Use "o" constraint
instead of "m" for double-word mode memory operands.
(*add3_doubleword_zext): Ditto.
(*addv4_doubleword_1): Use "jO" constraint instead of "jM"
for double-word mode memory operands.

Diff:
---
 gcc/config/i386/i386.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 0fae3c1eb878..8d269feee837 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3707,7 +3707,7 @@
   [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,r,r,&r")
(any_or_plus:DI
  (and:DI
-   (match_operand:DI 1 "nonimmediate_operand" "r,m,r,m")
+   (match_operand:DI 1 "nonimmediate_operand" "r,o,r,o")
(match_operand:DI 3 "const_int_operand" "n,n,n,n"))
  (zero_extend:DI
(match_operand:SI 2 "nonimmediate_operand" "r,r,m,m"]
@@ -6461,7 +6461,7 @@
(plus:
  (zero_extend:
(match_operand:DWIH 2 "nonimmediate_operand" "rm,r,rm,r"))
- (match_operand: 1 "nonimmediate_operand" "0,0,r,m")))
+ (match_operand: 1 "nonimmediate_operand" "0,0,r,o")))
(clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (UNKNOWN, mode, operands, TARGET_APX_NDD)"
   "#"
@@ -7703,7 +7703,7 @@
(eq:CCO
  (plus:
(sign_extend:
- (match_operand: 1 "nonimmediate_operand" "%0,rjM"))
+ (match_operand: 1 "nonimmediate_operand" "%0,rjO"))
(match_operand: 3 "const_scalar_int_operand" "n,n"))
  (sign_extend:
(plus:


[gcc r15-3553] SARIF output: fix schema URL [§3.13.3, PR116603]

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:38dc2c64710aa0e6a03c0c1201477e3e75b1a0b0

commit r15-3553-g38dc2c64710aa0e6a03c0c1201477e3e75b1a0b0
Author: David Malcolm 
Date:   Mon Sep 9 19:38:11 2024 -0400

SARIF output: fix schema URL [§3.13.3, PR116603]

We were using
  
https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json
as the URL for the SARIF 2.1 schema, but this is now a 404.

Update it to the URL listed in the spec (§3.13.3 "$schema property"),
which is:
  
https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json
and update the copy in
  gcc/testsuite/lib/sarif-schema-2.1.0.json
used by the "verify-sarif-file" DejaGnu directive to the version found at
that latter URL; the sha256 sum changes
from: 2b19d2358baef0251d7d24e208d05ffabf1b2a3ab5e1b3a816066fc57fd4a7e8
  to: c3b4bb2d6093897483348925aaa73af03b3e3f4bd4ca38cef26dcb4212a2682e

Doing so added a validation error on
  c-c++-common/diagnostic-format-sarif-file-pr111700.c
for which we emit this textual output:
  this-file-does-not-exist.c: warning: #warning message [-Wcpp]
with no line number, and these invalid SARIF regions within the
physical location of the warning:
  "region": {"startColumn": 2,
 "endColumn": 9},
  "contextRegion": {}

This is due to this directive:
  # 0 "this-file-does-not-exist.c"
with line number 0.

The patch fixes this by not creating regions that have startLine <= 0.

gcc/ChangeLog:
PR other/116603
* diagnostic-format-sarif.cc (SARIF_SCHEMA): Update URL.
(sarif_builder::maybe_make_region_object): Don't create regions
with startLine <= 0.
(sarif_builder::maybe_make_region_object_for_context): Likewise.

gcc/testsuite/ChangeLog:
PR other/116603
* gcc.dg/plugin/diagnostic-test-metadata-sarif.py (test_basics):
Update expected schema URL.
* gcc.dg/plugin/diagnostic-test-paths-multithreaded-sarif.py:
Likewise.
* gcc.dg/sarif-output/test-include-chain-1.py: Likewise.
* gcc.dg/sarif-output/test-include-chain-2.py: Likewise.
* gcc.dg/sarif-output/test-missing-semicolon.py: Likewise.
* gcc.dg/sarif-output/test-no-diagnostics.py: Likewise.
* gcc.dg/sarif-output/test-werror.py: Likewise.
* lib/sarif-schema-2.1.0.json: Update with copy downloaded from

https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-sarif.cc | 25 ++--
 .../plugin/diagnostic-test-metadata-sarif.py   |  2 +-
 .../diagnostic-test-paths-multithreaded-sarif.py   |  2 +-
 .../gcc.dg/sarif-output/test-include-chain-1.py|  2 +-
 .../gcc.dg/sarif-output/test-include-chain-2.py|  2 +-
 .../gcc.dg/sarif-output/test-missing-semicolon.py  |  2 +-
 .../gcc.dg/sarif-output/test-no-diagnostics.py |  2 +-
 gcc/testsuite/gcc.dg/sarif-output/test-werror.py   |  2 +-
 gcc/testsuite/lib/sarif-schema-2.1.0.json  | 73 ++
 9 files changed, 72 insertions(+), 40 deletions(-)

diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 9d9e7ae60734..e95f18f31bda 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -2221,7 +2221,10 @@ sarif_builder::get_sarif_column (expanded_location 
exploc) const
or return nullptr.
 
If COLUMN_OVERRIDE is non-zero, then use it as the column number
-   if LOC has no column information.  */
+   if LOC has no column information.
+
+   We only support text properties of regions ("text regions"),
+   not binary properties ("binary regions"); see 3.30.1.  */
 
 std::unique_ptr
 sarif_builder::maybe_make_region_object (location_t loc,
@@ -2244,11 +2247,16 @@ sarif_builder::maybe_make_region_object (location_t loc,
   if (exploc_finish.file !=exploc_caret.file)
 return nullptr;
 
+  /* We can have line == 0 in the presence of "#" lines.
+ SARIF requires lines > 0, so if we hit this case we don't have a
+ way of validly representing the region as SARIF; bail out.  */
+  if (exploc_start.line <= 0)
+return nullptr;
+
   auto region_obj = ::make_unique ();
 
   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
-  if (exploc_start.line > 0)
-region_obj->set_integer ("startLine", exploc_start.line);
+  region_obj->set_integer ("startLine", exploc_start.line);
 
   /* "startColumn" property (SARIF v2.1.0 section 3.30.6).
 
@@ -2316,11 +2324,16 @@ maybe_make_region_object_for_context (location_t loc,
   if (exploc_finish.file !=exploc_caret.file)
 return nullptr;
 
+  /* We can have line == 0 in the presence of "#" lines.
+ SARIF requires lines > 0, so if we hit this case we don't have a
+ wa

[gcc r15-3555] diagnostics: replace option_hooks with a diagnostic_option_manager class

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a97448e92eb76a69b4183183d14a791f9b76cc8d

commit r15-3555-ga97448e92eb76a69b4183183d14a791f9b76cc8d
Author: David Malcolm 
Date:   Mon Sep 9 19:38:12 2024 -0400

diagnostics: replace option_hooks with a diagnostic_option_manager class

Introduce a diagnostic_option_manager class to help isolate the
diagnostics subsystem from GCC's option handling.

No functional change intended.

gcc/ChangeLog:
* diagnostic.cc (diagnostic_context::initialize): Replace
m_options_callbacks with m_option_mgr.
(diagnostic_context::set_option_hooks): Replace with...
(diagnostic_context::set_option_manager): ...this.
* diagnostic.h (diagnostic_option_enabled_cb): Delete.
(diagnostic_make_option_name_cb): Delete.
(diagnostic_make_option_url_cb): Delete.
(class diagnostic_option_manager): New.
(diagnostic_manager::option_enabled_p): Convert from using
m_option_callbacks to m_option_mgr.
(diagnostic_manager::make_option_name): Likewise.
(diagnostic_manager::make_option_url): Likewise.
(diagnostic_manager::set_option_hooks): Replace with...
(diagnostic_manager::set_option_manager): ...this.
(diagnostic_manager::get_lang_mask): Update for field changes.
(diagnostic_manager::m_option_callbacks): Replace with...
(diagnostic_manager::m_option_mgr): ...this and...
(diagnostic_manager::m_lang_mask): ...this.
* lto-wrapper.cc (class lto_diagnostic_option_manager): New.
(main): Port from option hooks to diagnostic_option_manager.
* opts-common.cc: Include "opts-diagnostic.h".
(compiler_diagnostic_option_manager::option_enabled_p): New.
* opts-diagnostic.h (option_name): Drop decl.
(get_option_url): Drop decl.
(class gcc_diagnostic_option_manager): New.
(class compiler_diagnostic_option_manager): New.
* opts.cc (option_name): Convert to...
(compiler_diagnostic_option_manager::make_option_name): ...this.
(get_option_url): Convert to...
(gcc_diagnostic_option_manager::make_option_url): ...this.
* toplev.cc (general_init): Port from option hooks to
diagnostic_option_manager.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic.cc | 23 -
 gcc/diagnostic.h  | 94 ++-
 gcc/lto-wrapper.cc| 24 ++---
 gcc/opts-common.cc|  7 
 gcc/opts-diagnostic.h | 44 
 gcc/opts.cc   | 18 +-
 gcc/toplev.cc | 10 +++---
 7 files changed, 126 insertions(+), 94 deletions(-)

diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 32eab7d5407a..0e0ab7aeb838 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -226,10 +226,7 @@ diagnostic_context::initialize (int n_opts)
   m_text_callbacks.m_begin_diagnostic = default_diagnostic_starter;
   m_text_callbacks.m_start_span = default_diagnostic_start_span_fn;
   m_text_callbacks.m_end_diagnostic = default_diagnostic_finalizer;
-  m_option_callbacks.m_option_enabled_cb = nullptr;
-  m_option_callbacks.m_option_state = nullptr;
-  m_option_callbacks.m_make_option_name_cb = nullptr;
-  m_option_callbacks.m_make_option_url_cb = nullptr;
+  m_option_mgr = nullptr;
   m_urlifier = nullptr;
   m_last_location = UNKNOWN_LOCATION;
   m_last_module = nullptr;
@@ -446,18 +443,12 @@ diagnostic_context::set_original_argv (unique_argv 
original_argv)
 }
 
 void
-diagnostic_context::
-set_option_hooks (diagnostic_option_enabled_cb option_enabled_cb,
- void *option_state,
- diagnostic_make_option_name_cb make_option_name_cb,
- diagnostic_make_option_url_cb make_option_url_cb,
- unsigned lang_mask)
-{
-  m_option_callbacks.m_option_enabled_cb = option_enabled_cb;
-  m_option_callbacks.m_option_state = option_state;
-  m_option_callbacks.m_make_option_name_cb = make_option_name_cb;
-  m_option_callbacks.m_make_option_url_cb = make_option_url_cb;
-  m_option_callbacks.m_lang_mask = lang_mask;
+diagnostic_context::set_option_manager (diagnostic_option_manager *mgr,
+   unsigned lang_mask)
+{
+  delete m_option_mgr;
+  m_option_mgr = mgr;
+  m_lang_mask = lang_mask;
 }
 
 void
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 4d6147b87458..7244f425936c 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -181,14 +181,34 @@ typedef void (*diagnostic_finalizer_fn) 
(diagnostic_context *,
 const diagnostic_info *,
 diagnostic_t);
 
-typedef int (*diagnostic_option_enabled_cb) (int, unsigned, void *);
-typedef char *(*diagnostic_make_option_name_cb) (const diagnostic_context *,
- 

[gcc r15-3554] diagnostics: rename dc.printer to m_printer [PR116613]

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:19363bf5564ffbe992265a1e69a0d99a0d29f016

commit r15-3554-g19363bf5564ffbe992265a1e69a0d99a0d29f016
Author: David Malcolm 
Date:   Mon Sep 9 19:38:12 2024 -0400

diagnostics: rename dc.printer to m_printer [PR116613]

Rename diagnostic_context's "printer" field to "m_printer",
for consistency with other fields, and to highlight places
where we currently use this, to help assess feasibility
of supporting multiple output sinks (PR other/116613).

No functional change intended.

gcc/ChangeLog:
PR other/116613
* attribs.cc (decls_mismatched_attributes): Rename
diagnostic_context's "printer" field to "m_printer".
(attr_access::array_as_string): Likewise.
* diagnostic-format-json.cc
(json_output_format::on_report_diagnostic): Likewise.
(diagnostic_output_format_init_json): Likewise.
* diagnostic-format-sarif.cc
(sarif_result::on_nested_diagnostic): Likewise.
(sarif_ice_notification): Likewise.
(sarif_builder::on_report_diagnostic): Likewise.
(sarif_builder::make_result_object): Likewise.
(sarif_builder::make_location_object): Likewise.
(sarif_builder::make_message_object_for_diagram): Likewise.
(diagnostic_output_format_init_sarif): Likewise.
* diagnostic-format-text.cc
(diagnostic_text_output_format::~diagnostic_text_output_format):
Likewise.
(diagnostic_text_output_format::on_report_diagnostic): Likewise.
(diagnostic_text_output_format::on_diagram): Likewise.
(diagnostic_text_output_format::print_any_cwe): Likewise.
(diagnostic_text_output_format::print_any_rules): Likewise.
(diagnostic_text_output_format::print_option_information):
Likewise.
* diagnostic-format.h (diagnostic_output_format::get_printer):
New.
* diagnostic-global-context.cc (verbatim): Rename
diagnostic_context's "printer" field to "m_printer".
* diagnostic-path.cc (path_label::get_text): Likewise.
(print_path_summary_as_text): Likewise.
(diagnostic_context::print_path): Likewise.
(selftest::test_empty_path): Likewise.
(selftest::test_intraprocedural_path): Likewise.
(selftest::test_interprocedural_path_1): Likewise.
(selftest::test_interprocedural_path_2): Likewise.
(selftest::test_recursion): Likewise.
(selftest::test_control_flow_1): Likewise.
(selftest::test_control_flow_2): Likewise.
(selftest::test_control_flow_3): Likewise.
(assert_cfg_edge_path_streq): Likewise.
(selftest::test_control_flow_5): Likewise.
(selftest::test_control_flow_6): Likewise.
* diagnostic-show-locus.cc (layout::layout): Likewise.
(selftest::test_layout_x_offset_display_utf8): Likewise.
(selftest::test_layout_x_offset_display_tab): Likewise.
(selftest::test_diagnostic_show_locus_unknown_location): Likewise.
(selftest::test_one_liner_simple_caret): Likewise.
(selftest::test_one_liner_no_column): Likewise.
(selftest::test_one_liner_caret_and_range): Likewise.
(selftest::test_one_liner_multiple_carets_and_ranges): Likewise.
(selftest::test_one_liner_fixit_insert_before): Likewise.
(selftest::test_one_liner_fixit_insert_after): Likewise.
(selftest::test_one_liner_fixit_remove): Likewise.
(selftest::test_one_liner_fixit_replace): Likewise.
(selftest::test_one_liner_fixit_replace_non_equal_range):
Likewise.
(selftest::test_one_liner_fixit_replace_equal_secondary_range):
Likewise.
(selftest::test_one_liner_fixit_validation_adhoc_locations):
Likewise.
(selftest::test_one_liner_many_fixits_1): Likewise.
(selftest::test_one_liner_many_fixits_2): Likewise.
(selftest::test_one_liner_labels): Likewise.
(selftest::test_one_liner_simple_caret_utf8): Likewise.
(selftest::test_one_liner_caret_and_range_utf8): Likewise.
(selftest::test_one_liner_multiple_carets_and_ranges_utf8):
Likewise.
(selftest::test_one_liner_fixit_insert_before_utf8): Likewise.
(selftest::test_one_liner_fixit_insert_after_utf8): Likewise.
(selftest::test_one_liner_fixit_remove_utf8): Likewise.
(selftest::test_one_liner_fixit_replace_utf8): Likewise.
(selftest::test_one_liner_fixit_replace_non_equal_range_utf8):
Likewise.
(selftest::test_one_liner_fixit_replace_equal_secondary_range_utf8):
Likewise.
(selftest::test_one_liner_fixit_validation_adhoc_locations_

[gcc r15-3556] diagnostics: introduce struct diagnostic_option_id

2024-09-09 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:89991f31c5ded21179b12a9f4063c2b8fabc2e3b

commit r15-3556-g89991f31c5ded21179b12a9f4063c2b8fabc2e3b
Author: David Malcolm 
Date:   Mon Sep 9 19:38:13 2024 -0400

diagnostics: introduce struct diagnostic_option_id

Use a new struct diagnostic_option_id rather than just "int" when
referring to command-line options controlling warnings in the
diagnostic subsystem.

No functional change intended, but better documents the meaning of
the code.

gcc/c-family/ChangeLog:
* c-common.cc (c_option_controlling_cpp_diagnostic): Return
diagnostic_option_id rather than int.
(c_cpp_diagnostic): Update for renaming of
diagnostic_override_option_index to diagnostic_set_option_id.

gcc/c/ChangeLog:
* c-errors.cc (pedwarn_c23): Use "diagnostic_option_id option_id"
rather than "int opt".  Update for renaming of diagnostic_info
field.
(pedwarn_c11): Likewise.
(pedwarn_c99): Likewise.
(pedwarn_c90): Likewise.
* c-tree.h (pedwarn_c90): Likewise for decl.
(pedwarn_c99): Likewise.
(pedwarn_c11): Likewise.
(pedwarn_c23): Likewise.

gcc/cp/ChangeLog:
* constexpr.cc (constexpr_error): Update for renaming of
diagnostic_info field.
* cp-tree.h (pedwarn_cxx98): Use "diagnostic_option_id" rather
than "int".
* error.cc (cp_adjust_diagnostic_info): Update for renaming of
diagnostic_info field.
(pedwarn_cxx98): Use "diagnostic_option_id option_id" rather than
"int opt".  Update for renaming of diagnostic_info field.
(diagnostic_set_info): Likewise.

gcc/d/ChangeLog:
* d-diagnostic.cc (d_diagnostic_report_diagnostic): Update for
renaming of diagnostic_info field.

gcc/ChangeLog:
* diagnostic-core.h (struct diagnostic_option_id): New.
(warning): Use it rather than "int" for param.
(warning_n): Likewise.
(warning_at): Likewise.
(warning_meta): Likewise.
(pedwarn): Likewise.
(permerror_opt): Likewise.
(emit_diagnostic): Likewise.
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist_meta): Likewise.
* diagnostic-format-json.cc
(json_output_format::on_report_diagnostic): Update for renaming of
diagnostic_info field.
* diagnostic-format-sarif.cc (sarif_builder::make_result_object):
Likewise.
(make_reporting_descriptor_object_for_warning): Likewise.
* diagnostic-format-text.cc (print_option_information): Likewise.
* diagnostic-global-context.cc (emit_diagnostic): Use
"diagnostic_option_id option_id" rather than "int opt".
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist_meta): Likewise.
(warning): Likewise.
(warning_at): Likewise.
(warning_meta): Likewise.
(warning_n): Likewise.
(pedwarn): Likewise.
(permerror_opt): Likewise.
* diagnostic.cc (diagnostic_set_info_translated): Update for
renaming of diagnostic_info field.
(diagnostic_option_classifier::classify_diagnostic): Use
"diagnostic_option_id option_id" rather than "int opt".
(update_effective_level_from_pragmas): Update for renaming of
diagnostic_info field.
(diagnostic_context::diagnostic_enabled): Likewise.
(diagnostic_context::warning_enabled_at): Use
"diagnostic_option_id option_id" rather than "int opt".
(diagnostic_context::diagnostic_impl): Likewise.
(diagnostic_context::diagnostic_n_impl): Likewise.
* diagnostic.h (diagnostic_info::diagnostic_info): Update for...
(diagnostic_info::option_index): Rename...
(diagnostic_info::option_id): ...to this.
(class diagnostic_option_manager): Use
"diagnostic_option_id option_id" rather than "int opt" for vfuncs.
(diagnostic_option_classifier): Likewise for member funcs.
(diagnostic_classification_change_t::option): Add comment.
(diagnostic_context::warning_enabled_at): Use
"diagnostic_option_id option_id" rather than "int option_index".
(diagnostic_context::option_unspecified_p): Likewise.
(diagnostic_context::classify_diagnostic): Likewise.
(diagnostic_context::option_enabled_p): Likewise.
(diagnostic_context::make_option_name): Likewise.
(diagnostic_context::make_option_url): Likewise.
(diagnostic_context::diagnostic_impl): Likewise.
(diagnostic_context::diagnostic_n_impl): Likewise.
(diagnostic

[gcc r15-3558] Don't force_reg operands[3] when it's not const0_rtx.

2024-09-09 Thread hongtao Liu via Gcc-cvs
https://gcc.gnu.org/g:c726a6643125a59e2ba6f992924a2d0098104578

commit r15-3558-gc726a6643125a59e2ba6f992924a2d0098104578
Author: liuhongt 
Date:   Fri Sep 6 15:03:16 2024 +0800

Don't force_reg operands[3] when it's not const0_rtx.

It fix the regression by

a51f2fc0d80869ab079a93cc3858f24a1fd28237 is the first bad commit
commit a51f2fc0d80869ab079a93cc3858f24a1fd28237
Author: liuhongt 
Date:   Wed Sep 4 15:39:17 2024 +0800

Handle const0_operand for *avx2_pcmp3_1.

caused

FAIL: gcc.target/i386/pr59539-1.c scan-assembler-times vmovdqu|vmovups 1

To reproduce:

$ cd {build_dir}/gcc && make check 
RUNTESTFLAGS="i386.exp=gcc.target/i386/pr59539-1.c --target_board='unix{-m32\ 
-march=cascadelake}'"
$ cd {build_dir}/gcc && make check 
RUNTESTFLAGS="i386.exp=gcc.target/i386/pr59539-1.c --target_board='unix{-m64\ 
-march=cascadelake}'"

gcc/ChangeLog:

* config/i386/sse.md (*avx2_pcmp3_1): Don't force_reg
operands[3] when it's not const0_rtx.

Diff:
---
 gcc/config/i386/sse.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 1946d3513be1..1ae61182d0cc 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -17929,7 +17929,8 @@
   if (INTVAL (operands[5]) == 1)
 std::swap (operands[3], operands[4]);
 
-  operands[3] = force_reg (mode, operands[3]);
+  if (operands[3] == CONST0_RTX (mode))
+operands[3] = force_reg (mode, operands[3]);
   if (operands[4] == CONST0_RTX (mode))
 operands[4] = force_reg (mode, operands[4]);


[gcc r15-3559] phiopt: Use gimple_phi_result rather than PHI_RESULT [PR116643]

2024-09-09 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:1b4497d61d47420a625240a117175a707bddb8fc

commit r15-3559-g1b4497d61d47420a625240a117175a707bddb8fc
Author: Andrew Pinski 
Date:   Mon Sep 9 08:08:37 2024 -0700

phiopt: Use gimple_phi_result rather than PHI_RESULT [PR116643]

This converts the uses of PHI_RESULT in phiopt to be gimple_phi_result
instead. Since there was already a mismatch of uses here, it
would be good to use prefered one (gimple_phi_result) instead.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/116643
gcc/ChangeLog:

* tree-ssa-phiopt.cc (replace_phi_edge_with_variable): 
s/PHI_RESULT/gimple_phi_result/.
(factor_out_conditional_operation): Likewise.
(minmax_replacement): Likewise.
(spaceship_replacement): Likewise.
(cond_store_replacement): Likewise.
(cond_if_else_store_replacement_1): Likewise.

Signed-off-by: Andrew Pinski 

Diff:
---
 gcc/tree-ssa-phiopt.cc | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 06ec5875722b..bd8ede06a98c 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -97,7 +97,7 @@ replace_phi_edge_with_variable (basic_block cond_block,
 {
   basic_block bb = gimple_bb (phi);
   gimple_stmt_iterator gsi;
-  tree phi_result = PHI_RESULT (phi);
+  tree phi_result = gimple_phi_result (phi);
   bool deleteboth = false;
 
   /* Duplicate range info if they are the only things setting the target PHI.
@@ -373,7 +373,7 @@ factor_out_conditional_operation (edge e0, edge e1, gphi 
*phi,
 return NULL;
 
   /* Create a new PHI stmt.  */
-  result = PHI_RESULT (phi);
+  result = gimple_phi_result (phi);
   temp = make_ssa_name (TREE_TYPE (new_arg0), NULL);
 
   gimple_match_op new_op = arg0_op;
@@ -1684,7 +1684,7 @@ minmax_replacement (basic_block cond_bb, basic_block 
middle_bb, basic_block alt_
   tree smaller, larger, arg_true, arg_false;
   gimple_stmt_iterator gsi, gsi_from;
 
-  tree type = TREE_TYPE (PHI_RESULT (phi));
+  tree type = TREE_TYPE (gimple_phi_result (phi));
 
   gcond *cond = as_a  (*gsi_last_bb (cond_bb));
   enum tree_code cmp = gimple_cond_code (cond);
@@ -2022,7 +2022,7 @@ minmax_replacement (basic_block cond_bb, basic_block 
middle_bb, basic_block alt_
   /* Emit the statement to compute min/max.  */
   location_t locus = gimple_location (last_nondebug_stmt (cond_bb));
   gimple_seq stmts = NULL;
-  tree phi_result = PHI_RESULT (phi);
+  tree phi_result = gimple_phi_result (phi);
   result = gimple_build (&stmts, locus, minmax, TREE_TYPE (phi_result),
 arg0, arg1);
   result = gimple_build (&stmts, locus, ass_code, TREE_TYPE (phi_result),
@@ -2224,7 +2224,7 @@ minmax_replacement (basic_block cond_bb, basic_block 
middle_bb, basic_block alt_
 
   /* Emit the statement to compute min/max.  */
   gimple_seq stmts = NULL;
-  tree phi_result = PHI_RESULT (phi);
+  tree phi_result = gimple_phi_result (phi);
 
   /* When we can't use a MIN/MAX_EXPR still make sure the expression
  stays in a form to be recognized by ISA that map to IEEE x > y ? x : y
@@ -2298,7 +2298,7 @@ spaceship_replacement (basic_block cond_bb, basic_block 
middle_bb,
   edge e0, edge e1, gphi *phi,
   tree arg0, tree arg1)
 {
-  tree phires = PHI_RESULT (phi);
+  tree phires = gimple_phi_result (phi);
   if (!INTEGRAL_TYPE_P (TREE_TYPE (phires))
   || TYPE_UNSIGNED (TREE_TYPE (phires))
   || !tree_fits_shwi_p (arg0)
@@ -3399,7 +3399,7 @@ cond_store_replacement (basic_block middle_bb, 
basic_block join_bb,
   add_phi_arg (newphi, rhs, e0, locus);
   add_phi_arg (newphi, name, e1, locus);
 
-  new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi));
+  new_stmt = gimple_build_assign (lhs, gimple_phi_result (newphi));
 
   /* 4) Insert that PHI node.  */
   gsi = gsi_after_labels (join_bb);
@@ -3481,7 +3481,7 @@ cond_if_else_store_replacement_1 (basic_block then_bb, 
basic_block else_bb,
   add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus);
   add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus);
 
-  new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi));
+  new_stmt = gimple_build_assign (lhs, gimple_phi_result (newphi));
 
   /* 3) Insert that PHI node.  */
   gsi = gsi_after_labels (join_bb);


[gcc r15-3560] phiopt: Move the common code between pass_phiopt and pass_cselim into a seperate function

2024-09-09 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:b081e6c860eb9688d24365d39586bc1b4c3fe28b

commit r15-3560-gb081e6c860eb9688d24365d39586bc1b4c3fe28b
Author: Andrew Pinski 
Date:   Mon Sep 9 15:34:11 2024 -0700

phiopt: Move the common code between pass_phiopt and pass_cselim into a 
seperate function

When r14-303-gb9fedabe381cce was done, it was missed that some of the 
common parts could
be done in a template and a lambda could be used. This patch implements 
that. This new
function can be used later on to implement a simple ifcvt pass.

gcc/ChangeLog:

* tree-ssa-phiopt.cc (execute_over_cond_phis): New template 
function,
moved the common parts from 
pass_phiopt::execute/pass_cselim::execute.
(pass_phiopt::execute): Move the functon specific parts of the loop
into an lamdba.
(pass_cselim::execute): Likewise.

Signed-off-by: Andrew Pinski 

Diff:
---
 gcc/tree-ssa-phiopt.cc | 253 +++--
 1 file changed, 100 insertions(+), 153 deletions(-)

diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index bd8ede06a98c..5710bc32e611 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -3933,6 +3933,83 @@ gate_hoist_loads (void)
  && HAVE_conditional_move);
 }
 
+template 
+static void
+execute_over_cond_phis (func_type func)
+{
+  unsigned n, i;
+  basic_block *bb_order;
+  basic_block bb;
+  /* Search every basic block for COND_EXPR we may be able to optimize.
+
+ We walk the blocks in order that guarantees that a block with
+ a single predecessor is processed before the predecessor.
+ This ensures that we collapse inner ifs before visiting the
+ outer ones, and also that we do not try to visit a removed
+ block.  */
+  bb_order = single_pred_before_succ_order ();
+  n = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
+
+  for (i = 0; i < n; i++)
+{
+  basic_block bb1, bb2;
+  edge e1, e2;
+  bool diamond_p = false;
+
+  bb = bb_order[i];
+
+  /* Check to see if the last statement is a GIMPLE_COND.  */
+  gcond *cond_stmt = safe_dyn_cast  (*gsi_last_bb (bb));
+  if (!cond_stmt)
+   continue;
+
+  e1 = EDGE_SUCC (bb, 0);
+  bb1 = e1->dest;
+  e2 = EDGE_SUCC (bb, 1);
+  bb2 = e2->dest;
+
+  /* We cannot do the optimization on abnormal edges.  */
+  if ((e1->flags & EDGE_ABNORMAL) != 0
+ || (e2->flags & EDGE_ABNORMAL) != 0)
+   continue;
+
+  /* If either bb1's succ or bb2 or bb2's succ is non NULL.  */
+  if (EDGE_COUNT (bb1->succs) == 0
+ || EDGE_COUNT (bb2->succs) == 0)
+   continue;
+
+  /* Find the bb which is the fall through to the other.  */
+  if (EDGE_SUCC (bb1, 0)->dest == bb2)
+   ;
+  else if (EDGE_SUCC (bb2, 0)->dest == bb1)
+   {
+ std::swap (bb1, bb2);
+ std::swap (e1, e2);
+   }
+  else if (EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest
+  && single_succ_p (bb2))
+   {
+ diamond_p = true;
+ e2 = EDGE_SUCC (bb2, 0);
+ /* Make sure bb2 is just a fall through. */
+ if ((e2->flags & EDGE_FALLTHRU) == 0)
+   continue;
+   }
+  else
+   continue;
+
+  e1 = EDGE_SUCC (bb1, 0);
+
+  /* Make sure that bb1 is just a fall through.  */
+  if (!single_succ_p (bb1)
+ || (e1->flags & EDGE_FALLTHRU) == 0)
+   continue;
+
+  func (bb, bb1, bb2, e1, e2, diamond_p, cond_stmt);
+}
+  free (bb_order);
+}
+
 /* This pass tries to replaces an if-then-else block with an
assignment.  We have different kinds of transformations.
Some of these transformations are also performed by the ifcvt
@@ -4156,88 +4233,22 @@ unsigned int
 pass_phiopt::execute (function *)
 {
   bool do_hoist_loads = !early_p ? gate_hoist_loads () : false;
-  basic_block bb;
-  basic_block *bb_order;
-  unsigned n, i;
   bool cfgchanged = false;
 
   calculate_dominance_info (CDI_DOMINATORS);
   mark_ssa_maybe_undefs ();
 
-  /* Search every basic block for COND_EXPR we may be able to optimize.
-
- We walk the blocks in order that guarantees that a block with
- a single predecessor is processed before the predecessor.
- This ensures that we collapse inner ifs before visiting the
- outer ones, and also that we do not try to visit a removed
- block.  */
-  bb_order = single_pred_before_succ_order ();
-  n = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
-
-  for (i = 0; i < n; i++)
+  auto phiopt_exec = [&] (basic_block bb, basic_block bb1,
+ basic_block bb2, edge e1, edge e2,
+ bool diamond_p, gcond *cond_stmt)
 {
-  gphi *phi;
-  basic_block bb1, bb2;
-  edge e1, e2;
-  tree arg0, arg1;
-  bool diamond_p = false;
-
-  bb = bb_order[i];
-
-  /* Check to see if the last statement is a GIMPLE_COND.  */
-  gcond *cond_stmt = safe_dyn_cast  (*gs