This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, combine] Fix host-specific behavior in simplify_compare_const()
- From: Chung-Ju Wu <jasonwucj at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 28 Feb 2013 00:30:24 +0800
- Subject: [PATCH, combine] Fix host-specific behavior in simplify_compare_const()
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().
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;
Any comment for the patch?
Thanks,
jasonwucj