diff mbox

[combine] Try REG_EQUAL for nonzero_bits

Message ID 000601d015e4$3915ef50$ab41cdf0$@arm.com
State New
Headers show

Commit Message

Zhenqiang Chen Dec. 12, 2014, 8:18 a.m. UTC
> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Eric Botcazou
> Sent: Monday, November 24, 2014 5:41 PM
> To: Zhenqiang Chen
> Cc: gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH, combine] Try REG_EQUAL for nonzero_bits
> 
> > Thanks for the comments. I will compare the two nonzero_bits from src
> > and REG_EQUAL. Then select the smaller one.
> 
> They are masks so you can simply AND them before ORing the result.
> 
> > Do you know why it use " SET_SRC (set)" other than "src" for
> > num_sign_bit_copies?
> >
> > If it is "src", I should do the same for num_sign_bit_copies with 
> > REG_EQUAL info.
> 
> Probably historical reasons, let's not try to change that now.  You can
apply
> the same treatment to num_sign_bit_copies (you will need a comparison
> here) while preserving the "src" vs "SET_SRC (set)" discrepancy.

Thanks for the comments. Patch is updated.

zero.
 
@@ -1698,13 +1720,14 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx
set, void *data)
 	    src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (GET_MODE (x)));
 #endif
 
-	  /* Don't call nonzero_bits if it cannot change anything.  */
-	  if (rsp->nonzero_bits != ~(unsigned HOST_WIDE_INT) 0)
-	    rsp->nonzero_bits |= nonzero_bits (src, nonzero_bits_mode);
 	  num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x));
 	  if (rsp->sign_bit_copies == 0
 	      || rsp->sign_bit_copies > num)
 	    rsp->sign_bit_copies = num;
+
+	  /* Don't call nonzero_bits if it cannot change anything.  */
+	  if (rsp->nonzero_bits != ~(unsigned HOST_WIDE_INT) 0)
+	    update_rsp_from_reg_equal (rsp, insn, src, x);
 	}
       else
 	{

Comments

Eric Botcazou Dec. 15, 2014, 9:19 a.m. UTC | #1
> Thanks for the comments. Patch is updated.
> 
> diff --git a/gcc/combine.c b/gcc/combine.c
> index 1808f97..2e865d7 100644
> --- a/gcc/combine.c
> +++ b/gcc/combine.c
> @@ -1603,6 +1603,28 @@ setup_incoming_promotions (rtx_insn *first)
>      }
>  }
> 
> +/* Update RSP from INSN's REG_EQUAL note and SRC.  */
> +
> +static void
> +update_rsp_from_reg_equal (reg_stat_type *rsp, rtx_insn *insn, rtx src, rtx
> x)
> +{
> +  rtx reg_equal = insn ? find_reg_equal_equiv_note (insn) : NULL_RTX;
> +  unsigned HOST_WIDE_INT bits = nonzero_bits (src, nonzero_bits_mode);

Note that "src" has taken the SHORT_IMMEDIATES_SIGN_EXTEND path here.

> +  if (reg_equal)
> +    {
> +      unsigned int num = num_sign_bit_copies (XEXP (reg_equal, 0),
> +					      GET_MODE (x));
> +      bits &= nonzero_bits (XEXP (reg_equal, 0), nonzero_bits_mode);

But XEXP (reg_equal, 0) hasn't here.  If we want to treat the datum of the 
REG_EQUAL or REG_EQUIV note as equivalent to the SET_SRC (set), and I think we 
should (see for example combine.c:9650), there is a problem.

So I think we should create a new function, something along of:

/* If MODE has a precision lower than PREC and SRC is a non-negative constant
   that would appear negative in MODE, sign-extend SRC for use in nonzero_bits
   because some machines (maybe most) will actually do the sign-extension and
   this is the conservative approach.

   ??? For 2.5, try to tighten up the MD files in this regard
   instead of this kludge.  */

rtx
sign_extend_short_imm (rtx src, machine_mode mode, unsigned int prec)
{
  if (GET_MODE_PRECISION (mode) < prec
	&& CONST_INT_P (src)
	&& INTVAL (src) > 0
	&& val_signbit_known_set_p (mode, INTVAL (src)))
    src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (mode));

  return src;
}

and calls it from combine.c:1702

#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
  src = sign_extend_short_imm (src, GET_MODE (x), BITS_PER_WORD);
#endif

and from combine.c:9650

#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
  tem = sign_extend_short_imm (tem, GET_MODE (x), GET_MODE_PRECISION (mode));
#endif

Once this is done, the same thing needs to be applied to XEXP (reg_equal, 0) 
before it is sent to nonzero_bits.


> -	  /* Don't call nonzero_bits if it cannot change anything.  */
> -	  if (rsp->nonzero_bits != ~(unsigned HOST_WIDE_INT) 0)
> -	    rsp->nonzero_bits |= nonzero_bits (src, nonzero_bits_mode);
>  	  num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x));
>  	  if (rsp->sign_bit_copies == 0
> 
>  	      || rsp->sign_bit_copies > num)
> 
>  	    rsp->sign_bit_copies = num;
> +
> +	  /* Don't call nonzero_bits if it cannot change anything.  */
> +	  if (rsp->nonzero_bits != ~(unsigned HOST_WIDE_INT) 0)
> +	    update_rsp_from_reg_equal (rsp, insn, src, x);

Can't we improve on this?  rsp->sign_bit_copies is modified both here and in 
update_rsp_from_reg_equal, but rsp->nonzero_bits is modified only in the 
latter function.  There is no reason for this discrepancy, so they ought to be 
handled the same way, either entirely here or entirely in the function.
diff mbox

Patch

diff --git a/gcc/combine.c b/gcc/combine.c
index 1808f97..2e865d7 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1603,6 +1603,28 @@  setup_incoming_promotions (rtx_insn *first)
     }
 }
 
+/* Update RSP from INSN's REG_EQUAL note and SRC.  */
+
+static void
+update_rsp_from_reg_equal (reg_stat_type *rsp, rtx_insn *insn, rtx src, rtx
x)
+{
+  rtx reg_equal = insn ? find_reg_equal_equiv_note (insn) : NULL_RTX;
+  unsigned HOST_WIDE_INT bits = nonzero_bits (src, nonzero_bits_mode);
+
+  if (reg_equal)
+    {
+      unsigned int num = num_sign_bit_copies (XEXP (reg_equal, 0),
+					      GET_MODE (x));
+      bits &= nonzero_bits (XEXP (reg_equal, 0), nonzero_bits_mode);
+      rsp->nonzero_bits |= bits;
+
+      if (rsp->sign_bit_copies > num)
+	rsp->sign_bit_copies = num;
+    }
+  else
+    rsp->nonzero_bits |= bits;
+}
+
 /* Called via note_stores.  If X is a pseudo that is narrower than
    HOST_BITS_PER_WIDE_INT and is being set, record what bits are known