From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 87239 invoked by alias); 6 Feb 2017 03:11:42 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 85422 invoked by uid 89); 6 Feb 2017 03:10:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.4 required=5.0 tests=AWL,BAYES_20,SPF_NEUTRAL autolearn=no version=3.3.2 spammy=REGNO, xexp, XEXP, H*f:sk:b14a87b X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 06 Feb 2017 03:10:19 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1caZh1-0000XO-A3 for gcc@gcc.gnu.org; Sun, 05 Feb 2017 22:10:17 -0500 Received: from pb-smtp2.pobox.com ([64.147.108.71]:54507 helo=sasl.smtp.pobox.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1caZh1-0000XJ-4W for gcc@gcc.gnu.org; Sun, 05 Feb 2017 22:10:15 -0500 Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id A0D2D67151; Sun, 5 Feb 2017 22:10:14 -0500 (EST) Received: from pb-smtp2.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 97B9267150; Sun, 5 Feb 2017 22:10:14 -0500 (EST) Received: from localhost.localdomain (unknown [76.215.41.237]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pb-smtp2.pobox.com (Postfix) with ESMTPSA id A04CF6714C; Sun, 5 Feb 2017 22:10:12 -0500 (EST) From: Daniel Santos To: gcc , Uros Bizjak , Jan Hubicka Subject: [PATCH 6/8] [i386] Add patterns and predicates foutline-msabi-xlouges Date: Mon, 06 Feb 2017 03:11:00 -0000 Message-Id: <20170206031349.1440-6-daniel.santos@pobox.com> In-Reply-To: References: X-Pobox-Relay-ID: C703863E-EC19-11E6-9A81-A7617B1B28F4-06139138!pb-smtp2.pobox.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 64.147.108.71 X-IsSubscribed: yes X-SW-Source: 2017-02/txt/msg00012.txt.bz2 Adds the predicates save_multiple and restore_multiple to predicates.md, which are used by following patterns in sse.md: * save_multiple - insn that calls a save stub * restore_multiple - call_insn that calls a save stub and returns to the function to allow a sibling call (which should typically offer better optimization than the restore stub as the tail call) * restore_multiple_and_return - a jump_insn that returns from the function as a tail-call. * restore_multiple_leave_return - like the above, but restores the frame pointer before returning. Signed-off-by: Daniel Santos --- gcc/config/i386/predicates.md | 155 ++++++++++++++++++++++++++++++++++++++++++ gcc/config/i386/sse.md | 37 ++++++++++ 2 files changed, 192 insertions(+) diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 8f250a2e720..36fe8abc3f4 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1657,3 +1657,158 @@ (ior (match_operand 0 "register_operand") (and (match_code "const_int") (match_test "op == constm1_rtx")))) + +;; Return true if: +;; 1. first op is a symbol reference, +;; 2. >= 13 operands, and +;; 3. operands 2 to end is one of: +;; a. save a register to a memory location, or +;; b. restore stack pointer. +(define_predicate "save_multiple" + (match_code "parallel") +{ + const unsigned nregs = XVECLEN (op, 0); + rtx head = XVECEXP (op, 0, 0); + unsigned i; + + if (GET_CODE (head) != USE) + return false; + else + { + rtx op0 = XEXP (head, 0); + if (op0 == NULL_RTX || GET_CODE (op0) != SYMBOL_REF) + return false; + } + + if (nregs < 13) + return false; + + for (i = 2; i < nregs; i++) + { + rtx e, src, dest; + + e = XVECEXP (op, 0, i); + + switch (GET_CODE (e)) + { + case SET: + src = SET_SRC (e); + dest = SET_DEST (e); + + /* storing a register to memory. */ + if (GET_CODE (src) == REG && GET_CODE (dest) == MEM) + { + rtx addr = XEXP (dest, 0); + + /* Good if dest address is in RAX. */ + if (GET_CODE (addr) == REG + && REGNO (addr) == AX_REG) + continue; + + /* Good if dest address is offset of RAX. */ + if (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && REGNO (XEXP (addr, 0)) == AX_REG) + continue; + } + break; + + default: + break; + } + return false; + } + return true; +}) + +;; Return true if: +;; * first op is (return) or a a use (symbol reference), +;; * >= 14 operands, and +;; * operands 2 to end are one of: +;; - restoring a register from a memory location that's an offset of RSI. +;; - clobbering a reg +;; - adjusting SP +(define_predicate "restore_multiple" + (match_code "parallel") +{ + const unsigned nregs = XVECLEN (op, 0); + rtx head = XVECEXP (op, 0, 0); + unsigned i; + + switch (GET_CODE (head)) + { + case RETURN: + i = 3; + break; + + case USE: + { + rtx op0 = XEXP (head, 0); + + if (op0 == NULL_RTX || GET_CODE (op0) != SYMBOL_REF) + return false; + + i = 1; + break; + } + + default: + return false; + } + + if (nregs < i + 12) + return false; + + for (; i < nregs; i++) + { + rtx e, src, dest; + + e = XVECEXP (op, 0, i); + + switch (GET_CODE (e)) + { + case CLOBBER: + continue; + + case SET: + src = SET_SRC (e); + dest = SET_DEST (e); + + /* Restoring a register from memory. */ + if (GET_CODE (src) == MEM && GET_CODE (dest) == REG) + { + rtx addr = XEXP (src, 0); + + /* Good if src address is in RSI. */ + if (GET_CODE (addr) == REG + && REGNO (addr) == SI_REG) + continue; + + /* Good if src address is offset of RSI. */ + if (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && REGNO (XEXP (addr, 0)) == SI_REG) + continue; + + /* Good if adjusting stack pointer. */ + if (GET_CODE (dest) == REG + && REGNO (dest) == SP_REG + && GET_CODE (src) == PLUS + && GET_CODE (XEXP (src, 0)) == REG + && REGNO (XEXP (src, 0)) == SP_REG) + continue; + } + + /* Restoring stack pointer from another register. */ + if (GET_CODE (dest) == REG && REGNO (dest) == SP_REG + && GET_CODE (src) == REG) + continue; + break; + + default: + break; + } + return false; + } + return true; +}) diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index a19c8f2bc2e..b9db729c427 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -19885,3 +19885,40 @@ (match_operand:VI48_512 1 "nonimmediate_operand" "vm")))] "TARGET_AVX512VPOPCNTDQ" "vpopcnt\t{%1, %0|%0, %1}") + +;; Save multiple registers out-of-line. +(define_insn "save_multiple" + [(match_parallel 0 "save_multiple" + [(use (match_operand:P 1 "symbol_operand")) + (const_int 0) + ])] + "TARGET_SSE && TARGET_64BIT" + "call\t%P1") + +;; Restore multiple registers out-of-line. +(define_insn "restore_multiple" + [(match_parallel 0 "restore_multiple" + [(use (match_operand:P 1 "symbol_operand"))])] + "TARGET_SSE && TARGET_64BIT" + "call\t%P1") + +;; Restore multiple registers out-of-line and return. +(define_insn "restore_multiple_and_return" + [(match_parallel 0 "restore_multiple" + [(return) + (use (match_operand:P 1 "symbol_operand")) + (const_int 0) + ])] + "TARGET_SSE && TARGET_64BIT" + "jmp\t%P1") + +;; Restore multiple registers out-of-line when hard frame pointer is used, +;; perform the leave operation prior to returning (from the function). +(define_insn "restore_multiple_leave_return" + [(match_parallel 0 "restore_multiple" + [(return) + (use (match_operand:P 1 "symbol_operand")) + (const_int 1) + ])] + "TARGET_SSE && TARGET_64BIT" + "jmp\t%P1") -- 2.11.0