From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 58491 invoked by alias); 27 Apr 2017 08:05:08 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 58427 invoked by uid 89); 27 Apr 2017 08:05:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.4 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_LOW,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=199973, offer X-HELO: sasl.smtp.pobox.com Received: from pb-smtp2.pobox.com (HELO sasl.smtp.pobox.com) (64.147.108.71) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 27 Apr 2017 08:05:05 +0000 Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 79C74883B9; Thu, 27 Apr 2017 04:05:07 -0400 (EDT) Received: from pb-smtp2.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 73956883B8; Thu, 27 Apr 2017 04:05:07 -0400 (EDT) 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 AB51F883B1; Thu, 27 Apr 2017 04:05:05 -0400 (EDT) From: Daniel Santos To: gcc-patches , Uros Bizjak , Jan Hubicka Subject: [PATCH 09/12] [i386] Add patterns and predicates foutline-msabi-xlouges Date: Thu, 27 Apr 2017 08:05:00 -0000 Message-Id: <20170427080932.11703-9-daniel.santos@pobox.com> In-Reply-To: <49e81c0b-07a4-22df-d7c3-2439177ac7cf@pobox.com> References: <49e81c0b-07a4-22df-d7c3-2439177ac7cf@pobox.com> X-Pobox-Relay-ID: 39F010D2-2B20-11E7-BF11-C260AE2156B6-06139138!pb-smtp2.pobox.com X-IsSubscribed: yes X-SW-Source: 2017-04/txt/msg01343.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 e8ccb1e10c3..c9fe7274def 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -19997,3 +19997,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