From patchwork Thu Feb 9 23:47:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 140453 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 4A821B71A5 for ; Fri, 10 Feb 2012 10:47:40 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1329436061; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:Date:Message-ID:Subject:From:To: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=PZuTIJn 2eLMpWUgmtbmoxwxgKQg=; b=nO+XnEYmtQ1lKUowA9yn2FUTexisvw69qpyfXVG uy1GVklfJzC8r6238JyjlwGqeqnWCqQ5RU8MR1Qb1zjWSUCWigxG/ZlypNqmjdZW jaXc5K6OlEy7zEMp9jv45DnSA+RkeTLu3tvwBD4ztEYnoeTVh/KRY0s+LnumWvKu 8bxM= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:MIME-Version:Received:Received:Date:Message-ID:Subject:From:To:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=CKP9S6wiMDpv1n/YRHonMwnPNI8kF8Vq77vnh1PxsjQzD28Z/QnwB+PMJgQmwj VRPqrWzde8NoLdsGM2EDYWRiYtHFrAg0dWreStTYh+zfuzKA8FRu6rRWXbyyMp8I DYZGK9dLsR7UPHSDfoiwZqbb8j37F4lzkh2P8LLAe5Z2I=; Received: (qmail 5645 invoked by alias); 9 Feb 2012 23:47:36 -0000 Received: (qmail 5635 invoked by uid 22791); 9 Feb 2012 23:47:34 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_ZJ X-Spam-Check-By: sourceware.org Received: from mail-yx0-f175.google.com (HELO mail-yx0-f175.google.com) (209.85.213.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 09 Feb 2012 23:47:19 +0000 Received: by yenr5 with SMTP id r5so1297489yen.20 for ; Thu, 09 Feb 2012 15:47:18 -0800 (PST) MIME-Version: 1.0 Received: by 10.236.93.4 with SMTP id k4mr5716909yhf.114.1328831238646; Thu, 09 Feb 2012 15:47:18 -0800 (PST) Received: by 10.146.124.2 with HTTP; Thu, 9 Feb 2012 15:47:18 -0800 (PST) Date: Fri, 10 Feb 2012 00:47:18 +0100 Message-ID: Subject: [PATCH, rtl-optimization]: Fix post-reload compare elimination pre-pass From: Uros Bizjak To: gcc-patches@gcc.gnu.org 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 Hello! I am trying to enable post-reload compare elimination pass on x86, and I discovered a problem in the way redundant compares are eliminated. The problem lies in the assumption that: (1) All comparison patterns are represented as [(set (reg:CC) (compare:CC (reg) (immediate)))] which is not true for x86 or any target which exposes FLAGS_REG early and defines SELECT_CC_MODE. Following testcase: --cut here-- int test (int a, int b) { int lt = a + b < 0; int eq = a + b == 0; if (lt) return 1; return eq; } --cut here-- compiles to the following dump before entering post-reload compare elimination pass: (insn 8 4 9 2 (parallel [ (set (reg:SI 4 si [orig:60 D.1710 ] [60]) (plus:SI (reg/v:SI 5 di [orig:63 a ] [63]) (reg/v:SI 4 si [orig:64 b ] [64]))) (clobber (reg:CC 17 flags)) ]) cmp.c:3 253 {*addsi_1} (nil)) (insn 9 8 10 2 (set (reg:CCZ 17 flags) (compare:CCZ (reg:SI 4 si [orig:60 D.1710 ] [60]) (const_int 0 [0]))) cmp.c:4 2 {*cmpsi_ccno_1} (nil)) (note 10 9 33 2 NOTE_INSN_DELETED) (insn 33 10 34 2 (set (reg:QI 1 dx [65]) (eq:QI (reg:CCZ 17 flags) (const_int 0 [0]))) cmp.c:4 595 {*setcc_qi} (nil)) (insn 34 33 30 2 (set (reg:SI 1 dx [65]) (zero_extend:SI (reg:QI 1 dx [65]))) cmp.c:4 123 {*zero_extendqisi2_movzbl} (nil)) (insn 30 34 29 2 (set (reg/v:SI 0 ax [orig:59 eq ] [59]) (const_int 1 [0x1])) cmp.c:6 64 {*movsi_internal} (expr_list:REG_EQUAL (const_int 1 [0x1]) (nil))) (insn 29 30 31 2 (set (reg:CCGOC 17 flags) (compare:CCGOC (reg:SI 4 si [orig:60 D.1710 ] [60]) (const_int 0 [0]))) cmp.c:6 2 {*cmpsi_ccno_1} (nil)) (insn 31 29 25 2 (set (reg/v:SI 0 ax [orig:59 eq ] [59]) (if_then_else:SI (ge (reg:CCGOC 17 flags) (const_int 0 [0])) (reg:SI 1 dx [65]) (reg/v:SI 0 ax [orig:59 eq ] [59]))) cmp.c:6 903 {*movsicc_noc} (nil)) The redundant-compare elimination pre-pass blindly eliminates (insn 29) from the sequence. The elimination is done without updating the compare mode in (insn 9)! The correct approach would be to also update the compare mode of (insn 9) to the mode of targetm.cc_modes_compatible target hook, which in the case abowe would be (CCZmode, CCGOCmode) -> CCGOCmode. Attached patch fixes this problem by checking for mode compatibility of redundant compare with previous compare before elimination, and sets the mode of previous compare to mode, compatible with both compares. 2012-02-10 Uros Bizjak * compare-elim.c (find_comparisons_in_bb): Eliminate only compares having mode compatible with the mode of previous compare. Substitute compare mode of previous compare with the mode, compatible with eliminated and previous compare. Patch was bootstrapped and regression tested with additional x86 specific patch that enables post-reload compare eliminations on x86_64-pc-linux-gnu {,-m32}. The complete patch is attached to this message. Is RTL optimisation part of the patch OK for mainline SVN and 4.6 ? Uros. Index: compare-elim.c =================================================================== --- compare-elim.c (revision 184067) +++ compare-elim.c (working copy) @@ -297,11 +297,36 @@ find_comparisons_in_bb (struct dom_walk_data *data src = conforming_compare (insn); if (src) { + enum machine_mode src_mode = GET_MODE (src); + /* Eliminate a compare that's redundant with the previous. */ if (last_cmp_valid && rtx_equal_p (last_cmp->in_a, XEXP (src, 0)) && rtx_equal_p (last_cmp->in_b, XEXP (src, 1))) { + rtx flags, x; + enum machine_mode new_mode + = targetm.cc_modes_compatible (last_cmp->orig_mode, src_mode); + + /* New mode is incompatible with the previous compare mode. */ + if (new_mode == VOIDmode) + continue; + + if (new_mode != last_cmp->orig_mode) + { + flags = gen_rtx_REG (src_mode, targetm.flags_regnum); + + /* Generate new comparison for substitution. */ + x = gen_rtx_COMPARE (new_mode, XEXP (src, 0), XEXP (src, 1)); + x = gen_rtx_SET (VOIDmode, flags, x); + + if (!validate_change (last_cmp->insn, + &PATTERN (last_cmp->insn), x, false)) + continue; + + last_cmp->orig_mode = new_mode; + } + delete_insn (insn); continue; } @@ -311,7 +336,7 @@ find_comparisons_in_bb (struct dom_walk_data *data last_cmp->prev_clobber = last_clobber; last_cmp->in_a = XEXP (src, 0); last_cmp->in_b = XEXP (src, 1); - last_cmp->orig_mode = GET_MODE (SET_DEST (single_set (insn))); + last_cmp->orig_mode = src_mode; VEC_safe_push (comparison_struct_p, heap, all_compares, last_cmp); /* It's unusual, but be prepared for comparison patterns that Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 184067) +++ config/i386/i386.c (working copy) @@ -17778,6 +17778,11 @@ ix86_cc_modes_compatible (enum machine_mode m1, en || (m1 == CCGOCmode && m2 == CCGCmode)) return CCGCmode; + if (m1 == CCZmode && (m2 == CCGCmode || m2 == CCGOCmode)) + return m2; + else if (m2 == CCZmode && (m1 == CCGCmode || m1 == CCGOCmode)) + return m1; + switch (m1) { default: @@ -38685,6 +38690,9 @@ ix86_autovectorize_vector_sizes (void) #undef TARGET_EXPAND_TO_RTL_HOOK #define TARGET_EXPAND_TO_RTL_HOOK ix86_maybe_switch_abi +#undef TARGET_FLAGS_REGNUM +#define TARGET_FLAGS_REGNUM FLAGS_REG + #undef TARGET_LEGITIMATE_ADDRESS_P #define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p