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". 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). For example, for this C code: int foo(int a, int b, int c) { return ((a > c) | (a != b)) ? b : a; } Before the patch, the generated assembly for RISC-V is: foo: bgt a0, a2, .L4 bne a0, a1, .L4 ret .L4: mv a0, a1 ret After the patch, the generated assembly becomes: foo: mv a0, a1 ret 2024-10-22 Jovan Vukic <jovan.vu...@rt-rk.com> gcc/ChangeLog: * tree-ssa-phiopt.cc (rhs_is_fed_for_value_replacement): Add a new optimization opportunity for BIT_IOR_EXPR and a != b. (operand_equal_for_value_replacement): Ditto. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/phi-opt-same-3.c: New test. CONFIDENTIALITY: The contents of this e-mail are confidential and intended only for the above addressee(s). If you are not the intended recipient, or the person responsible for delivering it to the intended recipient, copying or delivering it to anyone else or using it in any unauthorized manner is prohibited and may be unlawful. If you receive this e-mail by mistake, please notify the sender and the systems administrator at straym...@rt-rk.com immediately.
--- .../gcc.dg/tree-ssa/phi-opt-same-3.c | 17 +++++++ gcc/tree-ssa-phiopt.cc | 48 ++++++++++++------- 2 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-same-3.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-same-3.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-same-3.c new file mode 100644 index 00000000000..f9838f177a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-same-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-phiopt2 -fdump-tree-optimized" } */ + +int f1(int a, int b, int c) +{ + if ((a > c) & (a == b)) return a; + return b; +} + +int f2(int a, int b, int c) +{ + if ((a > c) | (a != b)) return b; + return a; +} + +/* { dg-final { scan-tree-dump-not "if " "phiopt2" } } */ +/* { dg-final { scan-tree-dump-not "if " "optimized" } } */ diff --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) return false; } -/* RHS is a source argument in a BIT_AND_EXPR which feeds a conditional - of the form SSA_NAME NE 0. +/* RHS is a source argument in a BIT_AND_EXPR or BIT_IOR_EXPR which feeds + a conditional of the form SSA_NAME NE 0. - If RHS is fed by a simple EQ_EXPR comparison of two values, see if - the two input values of the EQ_EXPR match arg0 and arg1. + If RHS is fed by a simple EQ_EXPR or NE_EXPR comparison of two values, + see if the two input values of the comparison match arg0 and arg1. If so update *code and return TRUE. Otherwise return FALSE. */ static bool rhs_is_fed_for_value_replacement (const_tree arg0, const_tree arg1, - enum tree_code *code, const_tree rhs) + enum tree_code *code, const_tree rhs, + enum tree_code bit_expression_code) { /* Obviously if RHS is not an SSA_NAME, we can't look at the defining statement. */ @@ -1096,11 +1097,15 @@ rhs_is_fed_for_value_replacement (const_tree arg0, const_tree arg1, { gimple *def1 = SSA_NAME_DEF_STMT (rhs); - /* 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))) { - /* Finally verify the source operands of the EQ_EXPR are equal - to arg0 and arg1. */ + /* Finally verify the source operands of the EQ_EXPR or NE_EXPR + are equal to arg0 and arg1. */ tree op0 = gimple_assign_rhs1 (def1); tree op1 = gimple_assign_rhs2 (def1); if ((operand_equal_for_phi_arg_p (arg0, op0) @@ -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. Return FALSE otherwise. */ @@ -1139,27 +1145,33 @@ operand_equal_for_value_replacement (const_tree arg0, const_tree arg1, return true; /* Now handle more complex case where we have an EQ comparison - which feeds a BIT_AND_EXPR which feeds COND. + feeding a BIT_AND_EXPR, or a NE comparison feeding a BIT_IOR_EXPR, + which then feeds into COND. First verify that COND is of the form SSA_NAME NE 0. */ if (*code != NE_EXPR || !integer_zerop (rhs) || TREE_CODE (lhs) != SSA_NAME) return false; - /* 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; - /* Now verify arg0/arg1 correspond to the source arguments of an - EQ comparison feeding the BIT_AND_EXPR. */ + /* Now verify arg0/arg1 correspond to the source arguments of an EQ + comparison feeding the BIT_AND_EXPR or a NE comparison feeding the + BIT_IOR_EXPR. */ tree tmp = gimple_assign_rhs1 (def); - if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp)) + if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp, + gimple_assign_rhs_code (def))) return true; tmp = gimple_assign_rhs2 (def); - if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp)) + if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp, + gimple_assign_rhs_code (def))) return true; return false; -- 2.43.0