From patchwork Thu Aug 7 11:32:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyrylo Tkachov X-Patchwork-Id: 377818 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 29EB61400B5 for ; Thu, 7 Aug 2014 21:32:33 +1000 (EST) 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:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=OxmZ2ccgH8mLv9/Sa zP/0WoNA8RrvXgUxjsUNzi/9DHJUutRp/tH8oNLOgbdx8nyj5yY4g6GZrXFJ7pCO s2OwpNrQdnNLe9uzaz15dv6p9i1CFlL+NGWpm+uVrRAtBU0fTbAT4rECIjRdEYC3 ckUm4J9EqXwuGlr6ycb+lZzHdI= 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:cc:subject:references :in-reply-to:content-type; s=default; bh=6yv7JIYH83vwkWyAbyYx6Eo yOA0=; b=FsePD2oJtXnGGza6rKeo9rbeBd3lG3x9XCFMrwuHbVuhgLtnDxPt7Eo 73XV5TKGSSdnoXXtaZvWQxJqwRvAuqrkG0tA07xoEu9CxT5wpbirqF1YNsmlMyje d9V2EKc5SG3CH+5e74FB9QU7ekXQ14YD8PxVXRC3Undjp/i3aGTY= Received: (qmail 31200 invoked by alias); 7 Aug 2014 11:32:26 -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 31182 invoked by uid 89); 7 Aug 2014 11:32:23 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, SPF_PASS autolearn=ham version=3.3.2 X-HELO: service87.mimecast.com Received: from service87.mimecast.com (HELO service87.mimecast.com) (91.220.42.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 07 Aug 2014 11:32:22 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Thu, 07 Aug 2014 12:32:19 +0100 Received: from [10.1.208.24] ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Thu, 7 Aug 2014 12:32:18 +0100 Message-ID: <53E363C2.4000405@arm.com> Date: Thu, 07 Aug 2014 12:32:18 +0100 From: Kyrill Tkachov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 MIME-Version: 1.0 To: Richard Earnshaw CC: gcc-patches Subject: Re: [PATCH, AArch64] Use MOVN to generate 64-bit negative immediates where sensible References: <000001cf6ae4$059c2280$10d46780$@bolton@arm.com> <537605FF.8070700@arm.com> In-Reply-To: <537605FF.8070700@arm.com> X-MC-Unique: 114080712321906001 X-IsSubscribed: yes On 16/05/14 13:35, Richard Earnshaw wrote: > On 08/05/14 18:36, Ian Bolton wrote: >> Hi, >> >> It currently takes 4 instructions to generate certain immediates on >> AArch64 (unless we put them in the constant pool). >> >> For example ... >> >> long long >> ffffbeefcafebabe () >> { >> return 0xFFFFBEEFCAFEBABEll; >> } >> >> leads to ... >> >> mov x0, 0x47806 >> mov x0, 0xcafe, lsl 16 >> mov x0, 0xbeef, lsl 32 >> orr x0, x0, -281474976710656 >> >> The above case is tackled in this patch by employing MOVN >> to generate the top 32-bits in a single instruction ... >> >> mov x0, -71536975282177 >> movk x0, 0xcafe, lsl 16 >> movk x0, 0xbabe, lsl 0 >> >> Note that where at least two half-words are 0xffff, existing >> code that does the immediate in two instructions is still used.) >> >> Tested on standard gcc regressions and the attached test case. >> >> OK for commit? > What about: > > long long a() > { > return 0x1234ffff56789abcll; > } > > long long b() > { > return 0x12345678ffff9abcll; > } > > long long c() > { > return 0x123456789abcffffll; > } > > ? > > Surely these can also benefit from this sort of optimization, but it > looks as though you only handle the top 16 bits being set. Hi Richard, How about this rework of the patch? For code: long long foo () { return 0xFFFFBEEFCAFEBABEll; } long long a() { return 0x1234ffff56789abcll; } long long b() { return 0x12345678ffff9abcll; } long long c() { return 0x123456789abcffffll; } we now generate: foo: mov x0, -17730 movk x0, 0xcafe, lsl 16 movk x0, 0xbeef, lsl 32 ret .size foo, .-foo .align 2 .global a .type a, %function a: mov x0, -25924 movk x0, 0x5678, lsl 16 movk x0, 0x1234, lsl 48 ret .size a, .-a .align 2 .global b .type b, %function b: mov x0, -25924 movk x0, 0x5678, lsl 32 movk x0, 0x1234, lsl 48 ret .size b, .-b .align 2 .global c .type c, %function c: mov x0, -1698889729 movk x0, 0x5678, lsl 32 movk x0, 0x1234, lsl 48 ret 3 instructions are used in each case. Thanks, Kyrill 2014-08-07 Ian Bolton Kyrylo Tkachov * config/aarch64/aarch64.c (aarch64_expand_mov_immediate): Use MOVN when one of the half-words is 0xffff. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 0a7f441..2db91c7 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1005,7 +1005,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) unsigned HOST_WIDE_INT val; bool subtargets; rtx subtarget; - int one_match, zero_match; + int one_match, zero_match, first_not_ffff_match; gcc_assert (mode == SImode || mode == DImode); @@ -1106,29 +1106,48 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) one_match = 0; zero_match = 0; mask = 0xffff; + first_not_ffff_match = -1; for (i = 0; i < 64; i += 16, mask <<= 16) { - if ((val & mask) == 0) - zero_match++; - else if ((val & mask) == mask) + if ((val & mask) == mask) one_match++; + else + { + if (first_not_ffff_match < 0) + first_not_ffff_match = i; + if ((val & mask) == 0) + zero_match++; + } } if (one_match == 2) { - mask = 0xffff; - for (i = 0; i < 64; i += 16, mask <<= 16) + /* Set one of the quarters and then insert back into result. */ + mask = 0xffffll << first_not_ffff_match; + emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_INT (val | mask))); + emit_insn (gen_insv_immdi (dest, GEN_INT (first_not_ffff_match), + GEN_INT ((val >> first_not_ffff_match) + & 0xffff))); + return; + } + + if (one_match == 1) + { + /* Set either first three quarters or all but the third. */ + mask = 0xffffll << (16 - first_not_ffff_match); + emit_insn (gen_rtx_SET (VOIDmode, dest, + GEN_INT (val | mask | 0xffffffff00000000ull))); + + /* Now insert other two quarters. */ + for (i = first_not_ffff_match + 16, mask <<= (first_not_ffff_match << 1); + i < 64; i += 16, mask <<= 16) { if ((val & mask) != mask) - { - emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_INT (val | mask))); - emit_insn (gen_insv_immdi (dest, GEN_INT (i), - GEN_INT ((val >> i) & 0xffff))); - return; - } + emit_insn (gen_insv_immdi (dest, GEN_INT (i), + GEN_INT ((val >> i) & 0xffff))); } - gcc_unreachable (); + return; } if (zero_match == 2)