From patchwork Tue Oct 27 14:49:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyrylo Tkachov X-Patchwork-Id: 55628 Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp1840915lbq; Tue, 27 Oct 2015 07:49:52 -0700 (PDT) X-Received: by 10.68.221.230 with SMTP id qh6mr27945261pbc.20.1445957392572; Tue, 27 Oct 2015 07:49:52 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id rb3si62375568pbc.134.2015.10.27.07.49.52 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 27 Oct 2015 07:49:52 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-411691-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; spf=pass (google.com: domain of gcc-patches-return-411691-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-411691-patch=linaro.org@gcc.gnu.org; dkim=pass header.i=@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=s2LPUUbAvH82pZm1m7nvEpjZoET7aJIfytkah5o+Z+1ff6 hLsjHw/Rud2+8TrVsb0wQG+QviDJSVzZtfIBC/rFGhQZEwf+pLml6BLZu09rNUe7 LE1HmVF0PUT3Z3ua8JSV5k654YDcS0st5Ix40bcx1Jr0/YCC3cs4aBYDUhYL0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=2RQjYyPVcMi06iKwG5xPkBjOZMU=; b=ocxZZcruAVF6hL6HnBZs +baygoibmvOs1LaugeEbV9I0wOy+fVuocDjc1C8Dhdo7zyv2Ptw289jYCNbqdFjB DVtIy4lcUuZvEWFtmvghv1+EzXfdAsNnVqJGqLHuYwvYvnyPX34hnIKvQ6xlqGDZ 6pSEluxvkrcx4WyN1+JKgLw= Received: (qmail 9972 invoked by alias); 27 Oct 2015 14:49:39 -0000 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 Received: (qmail 9962 invoked by uid 89); 27 Oct 2015 14:49:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, SPF_PASS autolearn=ham version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (146.101.78.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 27 Oct 2015 14:49:36 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-19-0yBBl7LAQ2WTXZAi6ySSPg-1; Tue, 27 Oct 2015 14:49:31 +0000 Received: from [10.2.207.50] ([10.1.2.79]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 27 Oct 2015 14:49:31 +0000 Message-ID: <562F8EFB.9080000@arm.com> Date: Tue, 27 Oct 2015 14:49:31 +0000 From: Kyrill Tkachov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: GCC Patches Subject: [PATCH][RTL-ifcvt] PR rtl-optimization/67749: Do not emit separate SET insn in IF-ELSE case X-MC-Unique: 0yBBl7LAQ2WTXZAi6ySSPg-1 X-IsSubscribed: yes Hi all, This patch fixes the gcc.dg/ifcvt-2.c test for x86_64 where we were failing to if-convert. This was because in my patch at https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=228194 which tried to emit a SET to move the source of insn_a or insn_b (that came from the test block) into a temporary. A SET however, is not always enough. For example, on x86_64 in order for the resulting insn to be recognised it frequently needs to be in PARALLEL with a (clobber (reg:CC FLAGS_REG)). This leads to the insn not being recognised. So this patch removes that SET and instead generates a couple of temporary pseudos that gets passed on a bit later to the code that loads the operands into registers when they're not general_operand. This way we just modify the existing (recognisable) sets, allowing us to if-convert the testcase. Bootstrapped and tested on x86_64, arm, aarch64. Ok for trunk? Thanks, Kyrill 2015-10-27 Kyrylo Tkachov PR rtl-optimization/67749 * ifcvt.c (noce_try_cmove_arith): Do not emit move in IF-ELSE case before emitting the two blocks. Instead modify the register in the corresponding final insn of the basic block. commit d58740af39ceaf2d654cf3feff97b39fb6da3e82 Author: Kyrylo Tkachov Date: Tue Sep 29 13:44:21 2015 +0100 [RTL-ifcvt] PR rtl-optimization/67749 diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 8846e69..7c6e7ca 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -2135,38 +2135,29 @@ noce_try_cmove_arith (struct noce_if_info *if_info) emit might clobber the register used by B or A, so move it to a pseudo first. */ + rtx tmp_a = NULL_RTX; + rtx tmp_b = NULL_RTX; + if (b_simple || !else_bb) - { - rtx tmp_b = gen_reg_rtx (x_mode); - /* Perform the simplest kind of set. The register allocator - should remove it if it's not actually needed. If this set is not - a valid insn (can happen on the is_mem path) then end_ifcvt_sequence - will cancel the whole sequence. Don't try any of the fallback paths - from noce_emit_move_insn since we want this to be the simplest kind - of move. */ - emit_insn (gen_rtx_SET (tmp_b, b)); - b = tmp_b; - } + tmp_b = gen_reg_rtx (x_mode); if (a_simple || !then_bb) - { - rtx tmp_a = gen_reg_rtx (x_mode); - emit_insn (gen_rtx_SET (tmp_a, a)); - a = tmp_a; - } + tmp_a = gen_reg_rtx (x_mode); orig_a = a; orig_b = b; rtx emit_a = NULL_RTX; rtx emit_b = NULL_RTX; - + rtx_insn *tmp_insn = NULL; + bool modified_in_a = false; + bool modified_in_b = false; /* If either operand is complex, load it into a register first. The best way to do this is to copy the original insn. In this way we preserve any clobbers etc that the insn may have had. This is of course not possible in the IS_MEM case. */ - if (! general_operand (a, GET_MODE (a))) + if (! general_operand (a, GET_MODE (a)) || tmp_a) { if (is_mem) @@ -2174,36 +2165,51 @@ noce_try_cmove_arith (struct noce_if_info *if_info) rtx reg = gen_reg_rtx (GET_MODE (a)); emit_a = gen_rtx_SET (reg, a); } - else if (! insn_a) - goto end_seq_and_fail; else { - a = gen_reg_rtx (GET_MODE (a)); - rtx_insn *copy_of_a = as_a (copy_rtx (insn_a)); - rtx set = single_set (copy_of_a); - SET_DEST (set) = a; + if (insn_a) + { + a = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a)); + + rtx_insn *copy_of_a = as_a (copy_rtx (insn_a)); + rtx set = single_set (copy_of_a); + SET_DEST (set) = a; - emit_a = PATTERN (copy_of_a); + emit_a = PATTERN (copy_of_a); + } + else + { + rtx tmp_reg = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a)); + emit_a = gen_rtx_SET (tmp_reg, a); + a = tmp_reg; + } } } - if (! general_operand (b, GET_MODE (b))) + if (! general_operand (b, GET_MODE (b)) || tmp_b) { if (is_mem) { rtx reg = gen_reg_rtx (GET_MODE (b)); emit_b = gen_rtx_SET (reg, b); } - else if (! insn_b) - goto end_seq_and_fail; else { - b = gen_reg_rtx (GET_MODE (b)); - rtx_insn *copy_of_b = as_a (copy_rtx (insn_b)); - rtx set = single_set (copy_of_b); + if (insn_b) + { + b = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b)); + rtx_insn *copy_of_b = as_a (copy_rtx (insn_b)); + rtx set = single_set (copy_of_b); - SET_DEST (set) = b; - emit_b = PATTERN (copy_of_b); + SET_DEST (set) = b; + emit_b = PATTERN (copy_of_b); + } + else + { + rtx tmp_reg = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b)); + emit_b = gen_rtx_SET (tmp_reg, b); + b = tmp_reg; + } } } @@ -2211,16 +2217,35 @@ noce_try_cmove_arith (struct noce_if_info *if_info) swap insn that sets up A with the one that sets up B. If even that doesn't help, punt. */ - if (emit_a && modified_in_p (orig_b, emit_a)) - { - if (modified_in_p (orig_a, emit_b)) - goto end_seq_and_fail; + modified_in_a = emit_a != NULL_RTX && modified_in_p (orig_b, emit_a); + if (tmp_b && then_bb) + { + FOR_BB_INSNS (then_bb, tmp_insn) + if (modified_in_p (orig_b, tmp_insn)) + { + modified_in_a = true; + break; + } - if (else_bb && !b_simple) + } + if (emit_a && modified_in_a) + { + modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b); + if (tmp_b && else_bb) { - if (!noce_emit_bb (emit_b, else_bb, b_simple)) - goto end_seq_and_fail; + FOR_BB_INSNS (else_bb, tmp_insn) + if (modified_in_p (orig_a, tmp_insn)) + { + modified_in_b = true; + break; + } + } + if (modified_in_b) + goto end_seq_and_fail; + + if (!noce_emit_bb (emit_b, else_bb, b_simple)) + goto end_seq_and_fail; if (!noce_emit_bb (emit_a, then_bb, a_simple)) goto end_seq_and_fail;