diff mbox

[combine] Fix host-specific behavior in simplify_compare_const()

Message ID CADj25HMrO+PJ56EScQuW4irfO1__7M4fAwZy0ocyqgnHt2JhDQ@mail.gmail.com
State New
Headers show

Commit Message

Chung-Ju Wu Feb. 27, 2013, 4:30 p.m. UTC
Hi all,

I notice the function simplify_compare_const() in gcc/combine.c presents
different behavior between 32-bit host machine and 64-bit host machine,
causing it to perform different RTL transformation for a 32-bit target.

In the function: simplify_compare_const (enum rtx_code code, rtx op0,
rtx *pop1),
there is a statement "HOST_WIDE_INT const_op = INTVAL (*pop1);".
Although it uses "trunc_int_for_mode()" to make const_op
present the value for target machine mode,
the subsequent condition checking does not filter out the unnecessary bits:

  if (...
      ...
      && exact_log2 (const_op) >= 0
      && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op)
    {
      ...
    }

For example, given that:

op0: (and:SI (reg/v:SI 54)
             (const_int -2147483648))
*pop1: (const_int -2147483648)


Since mode comes from GET_MODE (op0), we know that mode is SImode.


on 32-bit host machine,

  rtx *pop1: (const_int -2147483648 [0x80000000])
  const_op: 0x80000000

  exact_log2 (const_op): 31
  nonzero_bits (op0, mode)         : 0x80000000
  (unsigned HOST_WIDE_INT) const_op: 0x80000000


on 64-bit host machine,

  rtx *pop1: (const_int -2147483648 [0xffffffff80000000])
  const_op: 0xffffffff80000000

  exact_log2 (const_op): -1
  nonzero_bits (op0, mode)         : 0x0000000080000000
  (unsigned HOST_WIDE_INT) const_op: 0xffffffff80000000


In this case, the condition results on 32-bit and 64-bit host machine
are different.
The result on 64-bit host machine cannot pass the condition test
so that we have no chance to do optimization.

In other words, any 32-bit target with 'need_64bit_hwint=yes' in config.gcc
is not able to have benefit from this optimization because it never
passes the condition test.


My solution is to use GET_MODE_MASK(mode) to filter out all bits not
in target mode.
The following is my patch:


gcc/ChangLog:

        * gcc/combine.c: Use GET_MODE_MASK() to filter out
        unnecessary bits in simplify_compare_const().


       code = (code == EQ || code == GE || code == GEU ? NE : EQ);
       const_op = 0;


Any comment for the patch?


Thanks,
jasonwucj

Comments

Eric Botcazou March 5, 2013, 11:58 a.m. UTC | #1
> In other words, any 32-bit target with 'need_64bit_hwint=yes' in config.gcc
> is not able to have benefit from this optimization because it never
> passes the condition test.
> 
> 
> My solution is to use GET_MODE_MASK(mode) to filter out all bits not
> in target mode. The following is my patch:

The patch is OK for 4.9 once stage #1 is open if it passes bootstrap/regtest.

> gcc/ChangLog:
> 
>         * gcc/combine.c: Use GET_MODE_MASK() to filter out
>         unnecessary bits in simplify_compare_const().

This should be

	* combine.c (simplify_compare_const): Use GET_MODE_MASK to filter out
	unnecessary bits in the constant power of two case.

> 
> diff --git a/gcc/combine.c b/gcc/combine.c
> index 67bd776..8c8cb92 100644
> --- a/gcc/combine.c
> +++ b/gcc/combine.c
> @@ -10917,8 +10917,8 @@ simplify_compare_const (enum rtx_code code,
> rtx op0, rtx *pop1)
>        && (code == EQ || code == NE || code == GE || code == GEU
> 
>           || code == LT || code == LTU)
> 
>        && mode_width <= HOST_BITS_PER_WIDE_INT
> -      && exact_log2 (const_op) >= 0
> -      && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op)
> +      && exact_log2 (const_op & GET_MODE_MASK (mode)) >= 0
> +      && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT)
> (const_op & GET_MODE_MASK (mode)))
>      {
>        code = (code == EQ || code == GE || code == GEU ? NE : EQ);
>        const_op = 0;

The line is too long, write

     && nonzero_bits (op0, mode)
        == (unsigned HOST_WIDE_INT) (const_op & GET_MODE_MASK (mode)))

instead.
diff mbox

Patch

diff --git a/gcc/combine.c b/gcc/combine.c
index 67bd776..8c8cb92 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -10917,8 +10917,8 @@  simplify_compare_const (enum rtx_code code,
rtx op0, rtx *pop1)
       && (code == EQ || code == NE || code == GE || code == GEU
          || code == LT || code == LTU)
       && mode_width <= HOST_BITS_PER_WIDE_INT
-      && exact_log2 (const_op) >= 0
-      && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op)
+      && exact_log2 (const_op & GET_MODE_MASK (mode)) >= 0
+      && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT)
(const_op & GET_MODE_MASK (mode)))
     {