[7/7] Expand directly for single bit test

Message ID 20230520021451.1901275-8-apinski@marvell.com
State Accepted
Headers
Series Improve do_store_flag |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Andrew Pinski May 20, 2023, 2:14 a.m. UTC
  Instead of using creating trees to the expansion,
just expand directly which makes the code a little simplier
but also reduces how much GC memory will be used during the expansion.

OK? Bootstrapped and tested on x86_64-linux.

gcc/ChangeLog:

	* expr.cc (fold_single_bit_test): Rename to ...
	(expand_single_bit_test): This and expand directly.
	(do_store_flag): Update for the rename function.
---
 gcc/expr.cc | 63 ++++++++++++++++++++++++-----------------------------
 1 file changed, 28 insertions(+), 35 deletions(-)
  

Comments

Jeff Law May 20, 2023, 4:55 a.m. UTC | #1
On 5/19/23 20:14, Andrew Pinski via Gcc-patches wrote:
> Instead of using creating trees to the expansion,
> just expand directly which makes the code a little simplier
> but also reduces how much GC memory will be used during the expansion.
> 
> OK? Bootstrapped and tested on x86_64-linux.
> 
> gcc/ChangeLog:
> 
> 	* expr.cc (fold_single_bit_test): Rename to ...
> 	(expand_single_bit_test): This and expand directly.
> 	(do_store_flag): Update for the rename function.
OK.

jeff
  

Patch

diff --git a/gcc/expr.cc b/gcc/expr.cc
index d04e8ed0204..6849c9627d0 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -12899,15 +12899,14 @@  maybe_optimize_sub_cmp_0 (enum tree_code code, tree *arg0, tree *arg1)
 }
 
 
-/* If CODE with arguments INNER & (1<<BITNUM) and 0 represents a single bit
-   equality/inequality test, then return a simplified form of
-   the test using shifts and logical operations.  Otherwise return
-   NULL.  TYPE is the desired result type.  */
+/* Expand CODE with arguments INNER & (1<<BITNUM) and 0 that represents
+   a single bit equality/inequality test, returns where the result is located.  */
 
-static tree
-fold_single_bit_test (location_t loc, enum tree_code code,
-		      tree inner, int bitnum,
-		      tree result_type)
+static rtx
+expand_single_bit_test (location_t loc, enum tree_code code,
+			tree inner, int bitnum,
+			tree result_type, rtx target,
+			machine_mode mode)
 {
   gcc_assert (code == NE_EXPR || code == EQ_EXPR);
 
@@ -12915,7 +12914,6 @@  fold_single_bit_test (location_t loc, enum tree_code code,
   scalar_int_mode operand_mode = SCALAR_INT_TYPE_MODE (type);
   int ops_unsigned;
   tree signed_type, unsigned_type, intermediate_type;
-  tree one;
   gimple *inner_def;
 
   /* First, see if we can fold the single bit test into a sign-bit
@@ -12924,10 +12922,11 @@  fold_single_bit_test (location_t loc, enum tree_code code,
       && type_has_mode_precision_p (type))
     {
       tree stype = signed_type_for (type);
-      return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
-			      result_type,
-			      fold_convert_loc (loc, stype, inner),
-			      build_int_cst (stype, 0));
+      tree tmp = fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+				  result_type,
+				  fold_convert_loc (loc, stype, inner),
+				  build_int_cst (stype, 0));
+      return expand_expr (tmp, target, VOIDmode, EXPAND_NORMAL);
     }
 
   /* Otherwise we have (A & C) != 0 where C is a single bit,
@@ -12957,21 +12956,21 @@  fold_single_bit_test (location_t loc, enum tree_code code,
   intermediate_type = ops_unsigned ? unsigned_type : signed_type;
   inner = fold_convert_loc (loc, intermediate_type, inner);
 
-  tree bftype = build_nonstandard_integer_type (1, 1);
-  int bitpos = bitnum;
-
-  if (BYTES_BIG_ENDIAN)
-    bitpos = GET_MODE_BITSIZE (operand_mode) - 1 - bitpos;
+  rtx inner0 = expand_expr (inner, target, VOIDmode, EXPAND_NORMAL);
 
-  inner = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
-		      bitsize_int (1), bitsize_int (bitpos));
-
-  one = build_int_cst (bftype, 1);
+  inner0 = extract_bit_field (inner0, 1, bitnum, 1, target,
+			      operand_mode, mode, 0, NULL);
 
   if (code == EQ_EXPR)
-    inner = fold_build2_loc (loc, BIT_XOR_EXPR, bftype, inner, one);
-
-  return fold_convert_loc (loc, result_type, inner);
+    inner0 = expand_binop (GET_MODE (inner0), xor_optab, inner0, const1_rtx,
+			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
+  if (GET_MODE (inner0) != mode)
+    {
+      rtx t = gen_reg_rtx (mode);
+      convert_move (t, inner0, 0);
+      return t;
+    }
+  return inner0;
 }
 
 /* Generate code to calculate OPS, and exploded expression
@@ -13150,10 +13149,7 @@  do_store_flag (sepops ops, rtx target, machine_mode mode)
      do this by shifting the bit being tested to the low-order bit and
      masking the result with the constant 1.  If the condition was EQ,
      we xor it with 1.  This does not require an scc insn and is faster
-     than an scc insn even if we have it.
-
-     The code to make this transformation was moved into fold_single_bit_test,
-     so we just call into the folder and expand its result.  */
+     than an scc insn even if we have it.  */
 
   if ((code == NE || code == EQ)
       && integer_zerop (arg1)
@@ -13163,16 +13159,13 @@  do_store_flag (sepops ops, rtx target, machine_mode mode)
       if (srcstmt
 	  && integer_pow2p (gimple_assign_rhs2 (srcstmt)))
 	{
-	  tree temp;
 	  enum tree_code tcode = code == NE ? NE_EXPR : EQ_EXPR;
 	  int bitnum = tree_log2 (gimple_assign_rhs2 (srcstmt));
 
 	  type = lang_hooks.types.type_for_mode (mode, unsignedp);
-	  temp = fold_single_bit_test (loc, tcode,
-				       gimple_assign_rhs1 (srcstmt),
-				       bitnum, type);
-	  if (temp)
-	    return expand_expr (temp, target, VOIDmode, EXPAND_NORMAL);
+	  return expand_single_bit_test (loc, tcode,
+					 gimple_assign_rhs1 (srcstmt),
+					 bitnum, type, target, mode);
 	}
     }