From 43aada7361f4f54e0c09ae46ac46ac982182135f Mon Sep 17 00:00:00 2001
From: Richard Biener <rguenther@suse.de>
Date: Thu, 19 Sep 2024 13:50:14 -0700
Subject: [PATCH 1/2] match: Fix `a != 0 ? a * b : 0` patterns for things that
 trap [PR116772]
To: gcc-patches@gcc.gnu.org

From: Andrew Pinski <quic_apinski@quicinc.com>

For generic, `a != 0 ? a * b : 0` would match where `b` would be an expression
which trap (in the case of the testcase, it was an integer division but it could be any).

This adds a new helper function, expr_no_side_effects_p which tests if there is no side effects
and the expression is not trapping which might be used in other locations.

Changes since v1:
* v2: Add move check to helper function instead of inlining it.

	PR middle-end/116772

gcc/ChangeLog:

	* generic-match-head.cc (expr_no_side_effects_p): New function
	* gimple-match-head.cc (expr_no_side_effects_p): New function

gcc/testsuite/ChangeLog:

	* gcc.dg/torture/pr116772-1.c: New test.

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
(cherry picked from commit 6c5543d3d9c4bbcd19f0ae2b7ed7e523c978a9a8)
---
 gcc/generic-match-head.cc                 | 12 ++++++++++++
 gcc/gimple-match-head.cc                  | 10 ++++++++++
 gcc/testsuite/gcc.dg/torture/pr116772-1.c | 24 +++++++++++++++++++++++
 3 files changed, 46 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr116772-1.c

diff --git a/gcc/generic-match-head.cc b/gcc/generic-match-head.cc
index 0d3f648fe8d..67ce95d3de5 100644
--- a/gcc/generic-match-head.cc
+++ b/gcc/generic-match-head.cc
@@ -105,6 +105,18 @@ optimize_successive_divisions_p (tree, tree)
   return false;
 }
 
+/* Returns true if the expression T has no side effects
+   including not trapping. */
+static inline bool
+expr_no_side_effects_p (tree t)
+{
+  if (TREE_SIDE_EFFECTS (t))
+    return false;
+  if (generic_expr_could_trap_p (t))
+    return false;
+  return true;
+}
+
 /* Return true if EXPR1 and EXPR2 have the same value, but not necessarily
    same type.  The types can differ through nop conversions.  */
 
diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc
index 5f8a1a1ad8e..697e69a5ba5 100644
--- a/gcc/gimple-match-head.cc
+++ b/gcc/gimple-match-head.cc
@@ -135,6 +135,16 @@ optimize_vectors_before_lowering_p ()
   return !cfun || (cfun->curr_properties & PROP_gimple_lvec) == 0;
 }
 
+/* Returns true if the expression T has no side effects
+   including not trapping. */
+static inline bool
+expr_no_side_effects_p (tree t)
+{
+  /* For gimple, there should only be gimple val's here. */
+  gcc_assert (is_gimple_val (t));
+  return true;
+}
+
 /* Return true if pow(cst, x) should be optimized into exp(log(cst) * x).
    As a workaround for SPEC CPU2017 628.pop2_s, don't do it if arg0
    is an exact integer, arg1 = phi_res +/- cst1 and phi_res = PHI <cst2, ...>
diff --git a/gcc/testsuite/gcc.dg/torture/pr116772-1.c b/gcc/testsuite/gcc.dg/torture/pr116772-1.c
new file mode 100644
index 00000000000..eedd0398af1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116772-1.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* PR middle-end/116772  */
+/* The division by `/b` should not
+   be made uncondtional. */
+
+int mult0(int a,int b) __attribute__((noipa));
+
+int mult0(int a,int b){
+  return (b!=0 ? (a/b)*b : 0);
+}
+
+int bit_and0(int a,int b) __attribute__((noipa));
+
+int bit_and0(int a,int b){
+  return (b!=0 ? (a/b)&b : 0);
+}
+
+int main() {
+  if (mult0(3, 0) != 0)
+    __builtin_abort();
+  if (bit_and0(3, 0) != 0)
+    __builtin_abort();
+  return 0;
+}
-- 
2.51.0


From 2f5346f25100e26624e375a5ce27bcada0b5358b Mon Sep 17 00:00:00 2001
From: Richard Biener <rguenther@suse.de>
Date: Fri, 30 Jan 2026 15:32:39 +0100
Subject: [PATCH 2/2] middle-end/123887 - trapping conditional operand turned
 unconditional
To: gcc-patches@gcc.gnu.org

The following properly checks expr_no_side_effects_p on two patterns
that turns a conditionally evaluated operand into unconditonal.

	PR middle-end/123887
	* match.pd ((zero_one ==/!= 0) ? .. z <op> y .. -> zero_one * z ..):
	Check evaluating z unconditionally has no side-effects, like
	trapping.

	* gcc.dg/torture/pr123887.c: New testcase.

(cherry picked from commit c1fa15791ae458e1bd8db6842dfc021230521a65)
---
 gcc/match.pd                            |  6 ++++--
 gcc/testsuite/gcc.dg/torture/pr123887.c | 14 ++++++++++++++
 2 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr123887.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 60aa87e3d37..1d5a90e3317 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4249,7 +4249,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         (op:c @2 @1))
   (if (INTEGRAL_TYPE_P (type)
        && TYPE_PRECISION (type) > 1
-       && (INTEGRAL_TYPE_P (TREE_TYPE (@0))))
+       && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && expr_no_side_effects_p (@2))
        (op (mult (convert:type @0) @2) @1))))
 
 /* (zero_one != 0) ? z <op> y : y -> ((typeof(y))zero_one * z) <op> y */
@@ -4261,7 +4262,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         @1)
   (if (INTEGRAL_TYPE_P (type)
        && TYPE_PRECISION (type) > 1
-       && (INTEGRAL_TYPE_P (TREE_TYPE (@0))))
+       && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && expr_no_side_effects_p (@2))
        (op (mult (convert:type @0) @2) @1))))
 
 /* ?: Value replacement. */
diff --git a/gcc/testsuite/gcc.dg/torture/pr123887.c b/gcc/testsuite/gcc.dg/torture/pr123887.c
new file mode 100644
index 00000000000..c2a9659c5b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr123887.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+
+typedef struct {
+    unsigned s;
+} struct_t;
+
+struct_t *p;
+_Bool cond;
+int v = 1;
+int main()
+{
+  int u = 1 + (cond ? p->s : 0);
+  return u - v;
+}
-- 
2.51.0

