From patchwork Fri May 27 13:17:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 97680 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 5D931B6F8D for ; Fri, 27 May 2011 23:17:40 +1000 (EST) Received: (qmail 1354 invoked by alias); 27 May 2011 13:17:38 -0000 Received: (qmail 1318 invoked by uid 22791); 27 May 2011 13:17:37 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL, BAYES_00, NO_DNS_FOR_FROM, TW_XF, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 27 May 2011 13:17:23 +0000 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 27 May 2011 06:17:23 -0700 X-ExtLoop1: 1 Received: from gnu-6.sc.intel.com ([10.3.194.135]) by orsmga001.jf.intel.com with ESMTP; 27 May 2011 06:17:22 -0700 Received: by gnu-6.sc.intel.com (Postfix, from userid 500) id D22C3180D86; Fri, 27 May 2011 06:17:22 -0700 (PDT) Date: Fri, 27 May 2011 06:17:22 -0700 From: "H.J. Lu" To: gcc-patches@gcc.gnu.org Cc: Eric Botcazou Subject: PATCH: PR rtl-optimization/49088: Combine fails to properly handle zero-extension and signed int constant Message-ID: <20110527131722.GA8529@intel.com> Reply-To: "H.J. Lu" MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 Date: Sat May 21 06:20:09 2011 -0700 Properly handle CONST_INT operands. 2011-05-21 H.J. Lu 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 + + 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 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. */