PATCH: PR rtl-optimization/49088: Combine fails to properly handle zero-extension and signed int constant
H.J. Lu
hongjiu.lu@intel.com
Fri May 27 14:07:00 GMT 2011
Hi,
When combine sees:
(insn 5 2 7 2 (parallel [
(set (reg/f:DI 61)
(plus:DI (reg/f:DI 20 frame)
(const_int -64 [0xffffffffffffffc0])))
(clobber (reg:CC 17 flags))
]) x.i:12 252 {*adddi_1}
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil)))
(insn 17 9 18 2 (parallel [
(set (reg:SI 72)
(plus:SI (subreg:SI (reg/f:DI 61) 0)
(const_int 6 [0x6])))
(clobber (reg:CC 17 flags))
]) x.i:14 251 {*addsi_1}
(expr_list:REG_DEAD (reg/f:DI 61)
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil))))
(insn 18 17 10 2 (set (reg:DI 73)
(zero_extend:DI (reg:SI 72))) x.i:14 112
{*zero_extendsidi2_rex64}
(expr_list:REG_DEAD (reg:SI 72)
(nil)))
(insn 11 10 12 2 (set (reg:DI 68)
(reg:DI 73)) x.i:14 62 {*movdi_internal_rex64}
(expr_list:REG_DEAD (reg:DI 73)
(nil)))
it was turned into
(insn 18 17 10 2 (set (reg:DI 73)
(const_int 4294967238 [0xffffffc6])) x.i:14 62
{*movdi_internal_rex64}
(nil))
(insn 11 10 12 2 (set (reg:DI 68)
(plus:DI (reg/f:DI 20 frame)
(reg:DI 73))) x.i:14 247 {*lea_1}
(expr_list:REG_DEAD (reg:DI 73)
(nil)))
force_to_mode has
/* If X is a CONST_INT, return a new one. Do this here since the
test below will fail. */
if (CONST_INT_P (x))
{
if (SCALAR_INT_MODE_P (mode))
return gen_int_mode (INTVAL (x) & mask, mode);
else
{
x = GEN_INT (INTVAL (x) & mask);
return gen_lowpart_common (mode, x);
}
}
/* If X is narrower than MODE and we want all the bits in X's mode, just
get X in the proper mode. */
if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode)
&& (GET_MODE_MASK (GET_MODE (x)) & ~mask) == 0)
return gen_lowpart (mode, x);
When it gets
(zero_extend:DI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0)
(const_int -58 [0xffffffffffffffc6])))
It first sets mask to 32bit and leads to
(subreg:DI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0)
(const_int -58 [0xffffffffffffffc6])) 0)
with mask == 0xffffffff. The probem is
binop:
/* For most binary operations, just propagate into the operation and
change the mode if we have an operation of that mode. */
op0 = force_to_mode (XEXP (x, 0), mode, mask, next_select);
op1 = force_to_mode (XEXP (x, 1), mode, mask, next_select);
where it calls force_to_mode with -58, 0xffffffff mask and DImode. This
transformation is incorrect. This patch changes mask to MODE_MASK of
mode if all the bits in CONST_INT are used. OK for trunk?
Thanks.
H.J.
---
commit 3a590e037128ba64d74fb7b323d2a4d19a02248f
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Sat May 21 06:20:09 2011 -0700
Properly handle CONST_INT operands.
2011-05-21 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/49088
* combine.c (force_to_mode): If X is narrower than MODE and we
want all the bits in X's mode, just use the operand when it
is CONST_INT.
diff --git a/gcc/ChangeLog.x32 b/gcc/ChangeLog.x32
index abd57a4..bf844ea 100644
--- a/gcc/ChangeLog.x32
+++ b/gcc/ChangeLog.x32
@@ -1,3 +1,10 @@
+2011-05-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR rtl-optimization/49088
+ * combine.c (force_to_mode): If X is narrower than MODE and we
+ want all the bits in X's mode, just use the operand when it
+ is CONST_INT.
+
2011-05-20 H.J. Lu <hongjiu.lu@intel.com>
PR target/48529
diff --git a/gcc/combine.c b/gcc/combine.c
index 8af86f2..710fe0e 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -8321,8 +8321,26 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
/* For most binary operations, just propagate into the operation and
change the mode if we have an operation of that mode. */
- op0 = force_to_mode (XEXP (x, 0), mode, mask, next_select);
- op1 = force_to_mode (XEXP (x, 1), mode, mask, next_select);
+ /* If X is narrower than MODE and we want all the bits in X's
+ mode, just use the operand when it is CONST_INT. */
+ if (SCALAR_INT_MODE_P (mode)
+ && GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode)
+ && (GET_MODE_MASK (GET_MODE (x)) & ~mask) == 0)
+ {
+ if (CONST_INT_P (XEXP (x, 0)))
+ op0 = XEXP (x, 0);
+ else
+ op0 = force_to_mode (XEXP (x, 0), mode, mask, next_select);
+ if (CONST_INT_P (XEXP (x, 1)))
+ op1 = XEXP (x, 1);
+ else
+ op1 = force_to_mode (XEXP (x, 1), mode, mask, next_select);
+ }
+ else
+ {
+ op0 = force_to_mode (XEXP (x, 0), mode, mask, next_select);
+ op1 = force_to_mode (XEXP (x, 1), mode, mask, next_select);
+ }
/* If we ended up truncating both operands, truncate the result of the
operation instead. */
More information about the Gcc-patches
mailing list