]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: Fix `a != 0 ? a * b : 0` patterns for things that trap [PR116772]
authorAndrew Pinski <quic_apinski@quicinc.com>
Thu, 19 Sep 2024 20:50:14 +0000 (13:50 -0700)
committerAndrew Pinski <quic_apinski@quicinc.com>
Wed, 25 Sep 2024 15:03:18 +0000 (08:03 -0700)
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
* match.pd (`a != 0 ? a / b : 0`): Check expr_no_side_effects_p.
(`a != 0 ? a * b : 0`, `a != 0 ? a & b : 0`): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
gcc/generic-match-head.cc
gcc/gimple-match-head.cc
gcc/match.pd
gcc/testsuite/gcc.dg/torture/pr116772-1.c [new file with mode: 0644]

index 641d8e9b2ded00ab9ee4f9914aef7307aef7a33f..42dee6266132dd1b260da2adcbe9b1d1cd2b48ac 100644 (file)
@@ -115,6 +115,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.  */
 
index b5d4a71ddc55f054e6ee15c1553577a3b6634a85..4147a0eb38a7d0fd6958921856d7dfb987567eaf 100644 (file)
@@ -145,6 +145,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, ...>
index d10ac7d6cd20730501b3d6648e08f4a97dffc6c3..cae3c5f6795a71a36afa6a158c084ce121912bde 100644 (file)
@@ -4728,7 +4728,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (simplify
   (cond (ne @0 integer_zerop) (op@2 @3 @1) integer_zerop )
    (if (bitwise_equal_p (@0, @3)
-        && tree_expr_nonzero_p (@1))
+        && tree_expr_nonzero_p (@1)
+       /* Cannot make a expression with side effects
+          unconditional. */
+       && expr_no_side_effects_p (@3))
     @2)))
 
 /* Note we prefer the != case here
@@ -4738,7 +4741,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (for op (mult bit_and)
  (simplify
   (cond (ne @0 integer_zerop) (op:c@2 @1 @3) integer_zerop)
-  (if (bitwise_equal_p (@0, @3))
+  (if (bitwise_equal_p (@0, @3)
+       /* Cannot make a expression with side effects
+          unconditional. */
+       && expr_no_side_effects_p (@1))
    @2)))
 
 /* Simplifications of shift and rotates.  */
diff --git a/gcc/testsuite/gcc.dg/torture/pr116772-1.c b/gcc/testsuite/gcc.dg/torture/pr116772-1.c
new file mode 100644 (file)
index 0000000..eedd039
--- /dev/null
@@ -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;
+}