On 10/22/24 2:32 AM, Jovan Vukic wrote:
Currently, within the phiopt pass, under value_replacement, we have the
option to replace the expression "(cond & (a == b)) ? a : b" with "b". It
checks whether there is a BIT_AND_EXPR and verifies if one of the operands
contains the expression "a == b".

However, the same result should also apply to the expression with the
inverted condition "(cond | (a != b)) ? b : a," so this patch makes slight
modifications to the existing code to cover this situation as well. The
patch adds a check for whether there is a BIT_IOR_EXPR and if it contains
"a != b".
Good catch.



I added a test for both optimizations, as I could not find an adequate test
in the testsuite for the first one (even though that optimization exists).
It looks like phi-opt-11.c could be a suitable test for the original commit. I found that by doing a git blame to find the commit id that added this code, then I looked that the entire patch for that commit and saw that it added phi-opt-11.c.




iff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 38cc8506d1f..956fe919cc0 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -1078,17 +1078,18 @@ jump_function_from_stmt (tree *arg, gimple *stmt)


- /* Verify the defining statement has an EQ_EXPR on the RHS. */
-      if (is_gimple_assign (def1) && gimple_assign_rhs_code (def1) == EQ_EXPR)
+      /* Verify the defining statement has an EQ_EXPR or NE_EXPR on the RHS.  
*/
+      if (is_gimple_assign (def1) &&
+         ((bit_expression_code == BIT_AND_EXPR &&
+           gimple_assign_rhs_code (def1) == EQ_EXPR) ||
+          (bit_expression_code == BIT_IOR_EXPR &&
+           gimple_assign_rhs_code (def1) == NE_EXPR)))
So a formatting nit. We bring the operator down, indented just inside the appropriate open paren rather than having the operator at the end of a line. ie

  if (foo
      && bar
      && (com || baz))

As an example.


@@ -1119,8 +1124,9 @@ rhs_is_fed_for_value_replacement (const_tree arg0, 
const_tree arg1,
/* Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND. - Also return TRUE if arg0/arg1 are equal to the source arguments of a - an EQ comparison feeding a BIT_AND_EXPR which feeds COND. + Also return TRUE if arg0/arg1 are equal to the source arguments of an
+   EQ comparison feeding a BIT_AND_EXPR, or NE comparison feeding a
+   BIT_IOR_EXPR which feeds COND.
So the A EQ/NE B expression, we can reverse A and B in the expression and still get the same result. But don't we have to be more careful for the TRUE/FALSE arms of the ternary? For BIT_AND we need ? a : b for BIT_IOR we need ? b : a.

I don't see that gets verified in the existing code or after your change. I suspect I'm just missing something here. Can you clarify how we verify that BIT_AND gets ? a : b for the true/false arms and that BIT_IOR gets ? b : a for the true/false arms?

As a patch to the generic part of the compiler, the required testing would be to bootstrap a platform like x86 before the patch, run the testsuite & capture the results. Then apply the patch, bootstrap again, run the testsuite again and compare the test results to ensure there are no regressions.




- /* Now ensure that SSA_NAME is set by a BIT_AND_EXPR. */
+  /* Now ensure that SSA_NAME is set by a BIT_AND_EXPR or BIT_OR_EXPR.  */
   def = SSA_NAME_DEF_STMT (lhs);
-  if (!is_gimple_assign (def) || gimple_assign_rhs_code (def) != BIT_AND_EXPR)
+  if (!is_gimple_assign (def) ||
+      (gimple_assign_rhs_code (def) != BIT_AND_EXPR &&
+       gimple_assign_rhs_code (def) != BIT_IOR_EXPR))
     return false;
So the formatting nit shows up here again.


So the biggest functional question is whether or not we're testing that for the new BIT_IOR case that we have ? b : a for the TRUE/FALSE arms.

And we need to get a confirmation that this bootstraps & regression tests cleanly on x86, aarch64 or one of the other tier1 platforms.

Thanks,
Jeff

Reply via email to