From patchwork Thu Dec 1 15:39:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Renlin Li X-Patchwork-Id: 701572 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 3tV1h83v54z9tlB for ; Fri, 2 Dec 2016 02:40:24 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="egT8s2A8"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=U9nq7LQAPGRT8NXVdqX/0UugQC3qFzwUcigOckdJnhqDR1fy+McS1 7P5CxFUUBk2SJHh6Fmxfm9gbyOGCNDjNL9hvBOR9bO0lu/buvs+ah7zetxqOBZkd 9BhTabzPTjfHkrxCM1sG0fikhsG8uu8lzu7Lx08l6tyEHsxpoDe/vk= 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:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=Ki3RAD03uGtC/ipmRVOhwb8sDjM=; b=egT8s2A8MbLJVX0dkD1U 878W6u+/utsIOBysib88glpfa/iPMCrZ1JRgYPwTxAk68nN0BZewlAOsYFHy+Sfk zFYwyD0hABInvLb7bUzb26rQNdt36362H/1gkWnO/ynNxMLVL2SNmI6wMwllDTjW 1BsHDd4PoTbK+b202LwYG1I= Received: (qmail 98568 invoked by alias); 1 Dec 2016 15:40:14 -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 98556 invoked by uid 89); 1 Dec 2016 15:40:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.8 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=9188, 3056, 7887, PAT X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 01 Dec 2016 15:40:03 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 31B39AD7; Thu, 1 Dec 2016 07:40:01 -0800 (PST) Received: from [10.2.207.43] (e104453-lin.cambridge.arm.com [10.2.207.43]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4E5F43F445; Thu, 1 Dec 2016 07:40:00 -0800 (PST) From: Renlin Li Subject: [PATCH][AARCH64]Simplify call, call_value, sibcall, sibcall_value patterns. To: "gcc-patches@gcc.gnu.org" , James Greenhalgh , Richard Henderson , Wilco Dijkstra , Ramana Radhakrishnan Message-ID: <5840444E.4020200@foss.arm.com> Date: Thu, 1 Dec 2016 15:39:58 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 X-IsSubscribed: yes Hi all, This patch refactors the code used in call, call_value, sibcall, sibcall_value expanders. Before the change, the logic is following: call expander --> call_internal --> call_reg/call_symbol call_vlaue expander --> call_value_internal --> call_value_reg/call_value_symbol sibcall expander --> sibcall_internal --> sibcall_insn sibcall_value expander --> sibcall_value_internal --> sibcall_value_insn After the change, the logic is simplified into: call expander --> aarch64_expand_call() --> call_insn call_value expander --> aarch64_expand_call() --> call_value_insn sibcall expander --> aarch64_expand_call() --> sibcall_insn sibcall_value expander --> aarch64_expand_call() --> sibcall_value_insn The code are factored out from each expander into aarch64_expand_call (). This also fixes the two issues Richard Henderson suggests in comments 8: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64971 aarch64-none-elf regression test Okay, aarch64-linux bootstrap Okay. Okay for trunk? Regards, Renlin Li gcc/ChangeLog: 2016-12-01 Renlin Li * config/aarch64/aarch64-protos.h (aarch64_expand_call): Declare. * config/aarch64/aarch64.c (aarch64_expand_call): Define. * config/aarch64/constraints.md (Usf): Add long call check. * config/aarch64/aarch64.md (call): Use aarch64_expand_call. (call_value): Likewise. (sibcall): Likewise. (sibcall_value): Likewise. (call_insn): New. (call_value_insn): New. (sibcall_insn): Update rtx pattern. (sibcall_value_insn): Likewise. (call_internal): Remove. (call_value_internal): Likewise. (sibcall_internal): Likewise. (sibcall_value_internal): Likewise. (call_reg): Likewise. (call_symbol): Likewise. (call_value_reg): Likewise. (call_value_symbol): Likewise. diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 7f67f14..3a5babb 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -305,6 +305,7 @@ bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT); bool aarch64_constant_address_p (rtx); bool aarch64_emit_approx_div (rtx, rtx, rtx); bool aarch64_emit_approx_sqrt (rtx, rtx, bool); +void aarch64_expand_call (rtx, rtx, bool); bool aarch64_expand_movmem (rtx *); bool aarch64_float_const_zero_rtx_p (rtx); bool aarch64_function_arg_regno_p (unsigned); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 68a3380..c313cf5 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -4343,6 +4343,51 @@ aarch64_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) return true; } +/* This function is used by the call expanders of the machine description. + RESULT is the register in which the result is returned. It's NULL for + "call" and "sibcall". + MEM is the location of the function call. + SIBCALL indicates whether this function call is normal call or sibling call. + It will generate different pattern accordingly. */ + +void +aarch64_expand_call (rtx result, rtx mem, bool sibcall) +{ + rtx call, callee, tmp; + rtvec vec; + machine_mode mode; + + gcc_assert (MEM_P (mem)); + callee = XEXP (mem, 0); + mode = GET_MODE (callee); + gcc_assert (mode == Pmode); + + /* Decide if we should generate indirect calls by loading the + 64-bit address of the callee into a register before performing + the branch-and-link. */ + + if (GET_CODE (callee) == SYMBOL_REF + ? (aarch64_is_long_call_p (callee) + || aarch64_is_noplt_call_p (callee)) + : !REG_P (callee)) + XEXP (mem, 0) = force_reg (mode, callee); + + call = gen_rtx_CALL (VOIDmode, mem, const0_rtx); + + if (result != NULL_RTX) + call = gen_rtx_SET (result, call); + + if (sibcall) + tmp = ret_rtx; + else + tmp = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM)); + + vec = gen_rtvec (2, call, tmp); + call = gen_rtx_PARALLEL (VOIDmode, vec); + + aarch64_emit_call_insn (call); +} + /* Emit call insn with PAT and do aarch64-specific handling. */ void diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index bc6d8a2..5682686 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -718,12 +718,6 @@ ;; Subroutine calls and sibcalls ;; ------------------------------------------------------------------- -(define_expand "call_internal" - [(parallel [(call (match_operand 0 "memory_operand" "") - (match_operand 1 "general_operand" "")) - (use (match_operand 2 "" "")) - (clobber (reg:DI LR_REGNUM))])]) - (define_expand "call" [(parallel [(call (match_operand 0 "memory_operand" "") (match_operand 1 "general_operand" "")) @@ -732,57 +726,22 @@ "" " { - rtx callee, pat; - - /* In an untyped call, we can get NULL for operand 2. */ - if (operands[2] == NULL) - operands[2] = const0_rtx; - - /* Decide if we should generate indirect calls by loading the - 64-bit address of the callee into a register before performing - the branch-and-link. */ - callee = XEXP (operands[0], 0); - if (GET_CODE (callee) == SYMBOL_REF - ? (aarch64_is_long_call_p (callee) - || aarch64_is_noplt_call_p (callee)) - : !REG_P (callee)) - XEXP (operands[0], 0) = force_reg (Pmode, callee); - - pat = gen_call_internal (operands[0], operands[1], operands[2]); - aarch64_emit_call_insn (pat); + aarch64_expand_call (NULL_RTX, operands[0], false); DONE; }" ) -(define_insn "*call_reg" - [(call (mem:DI (match_operand:DI 0 "register_operand" "r")) +(define_insn "*call_insn" + [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf")) (match_operand 1 "" "")) - (use (match_operand 2 "" "")) (clobber (reg:DI LR_REGNUM))] "" - "blr\\t%0" - [(set_attr "type" "call")] -) - -(define_insn "*call_symbol" - [(call (mem:DI (match_operand:DI 0 "" "")) - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (reg:DI LR_REGNUM))] - "GET_CODE (operands[0]) == SYMBOL_REF - && !aarch64_is_long_call_p (operands[0]) - && !aarch64_is_noplt_call_p (operands[0])" - "bl\\t%a0" - [(set_attr "type" "call")] + "@ + blr\\t%0 + bl\\t%a0" + [(set_attr "type" "call, call")] ) -(define_expand "call_value_internal" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "memory_operand" "") - (match_operand 2 "general_operand" ""))) - (use (match_operand 3 "" "")) - (clobber (reg:DI LR_REGNUM))])]) - (define_expand "call_value" [(parallel [(set (match_operand 0 "" "") (call (match_operand 1 "memory_operand" "") @@ -792,60 +751,23 @@ "" " { - rtx callee, pat; - - /* In an untyped call, we can get NULL for operand 3. */ - if (operands[3] == NULL) - operands[3] = const0_rtx; - - /* Decide if we should generate indirect calls by loading the - 64-bit address of the callee into a register before performing - the branch-and-link. */ - callee = XEXP (operands[1], 0); - if (GET_CODE (callee) == SYMBOL_REF - ? (aarch64_is_long_call_p (callee) - || aarch64_is_noplt_call_p (callee)) - : !REG_P (callee)) - XEXP (operands[1], 0) = force_reg (Pmode, callee); - - pat = gen_call_value_internal (operands[0], operands[1], operands[2], - operands[3]); - aarch64_emit_call_insn (pat); + aarch64_expand_call (operands[0], operands[1], false); DONE; }" ) -(define_insn "*call_value_reg" +(define_insn "*call_value_insn" [(set (match_operand 0 "" "") - (call (mem:DI (match_operand:DI 1 "register_operand" "r")) + (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf")) (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) (clobber (reg:DI LR_REGNUM))] "" - "blr\\t%1" - [(set_attr "type" "call")] - -) - -(define_insn "*call_value_symbol" - [(set (match_operand 0 "" "") - (call (mem:DI (match_operand:DI 1 "" "")) - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (reg:DI LR_REGNUM))] - "GET_CODE (operands[1]) == SYMBOL_REF - && !aarch64_is_long_call_p (operands[1]) - && !aarch64_is_noplt_call_p (operands[1])" - "bl\\t%a1" - [(set_attr "type" "call")] + "@ + blr\\t%1 + bl\\t%a1" + [(set_attr "type" "call, call")] ) -(define_expand "sibcall_internal" - [(parallel [(call (match_operand 0 "memory_operand" "") - (match_operand 1 "general_operand" "")) - (return) - (use (match_operand 2 "" ""))])]) - (define_expand "sibcall" [(parallel [(call (match_operand 0 "memory_operand" "") (match_operand 1 "general_operand" "")) @@ -853,29 +775,11 @@ (use (match_operand 2 "" ""))])] "" { - rtx pat; - rtx callee = XEXP (operands[0], 0); - if (!REG_P (callee) - && ((GET_CODE (callee) != SYMBOL_REF) - || aarch64_is_noplt_call_p (callee))) - XEXP (operands[0], 0) = force_reg (Pmode, callee); - - if (operands[2] == NULL_RTX) - operands[2] = const0_rtx; - - pat = gen_sibcall_internal (operands[0], operands[1], operands[2]); - aarch64_emit_call_insn (pat); + aarch64_expand_call (NULL_RTX, operands[0], true); DONE; } ) -(define_expand "sibcall_value_internal" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "memory_operand" "") - (match_operand 2 "general_operand" ""))) - (return) - (use (match_operand 3 "" ""))])]) - (define_expand "sibcall_value" [(parallel [(set (match_operand 0 "" "") (call (match_operand 1 "memory_operand" "") @@ -884,19 +788,7 @@ (use (match_operand 3 "" ""))])] "" { - rtx pat; - rtx callee = XEXP (operands[1], 0); - if (!REG_P (callee) - && ((GET_CODE (callee) != SYMBOL_REF) - || aarch64_is_noplt_call_p (callee))) - XEXP (operands[1], 0) = force_reg (Pmode, callee); - - if (operands[3] == NULL_RTX) - operands[3] = const0_rtx; - - pat = gen_sibcall_value_internal (operands[0], operands[1], operands[2], - operands[3]); - aarch64_emit_call_insn (pat); + aarch64_expand_call (operands[0], operands[1], true); DONE; } ) @@ -904,8 +796,7 @@ (define_insn "*sibcall_insn" [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf")) (match_operand 1 "" "")) - (return) - (use (match_operand 2 "" ""))] + (return)] "SIBLING_CALL_P (insn)" "@ br\\t%0 @@ -918,8 +809,7 @@ (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf")) (match_operand 2 "" ""))) - (return) - (use (match_operand 3 "" ""))] + (return)] "SIBLING_CALL_P (insn)" "@ br\\t%1 diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 7a2847a..bd28386 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -118,7 +118,8 @@ (define_constraint "Usf" "@internal Usf is a symbol reference under the context where plt stub allowed." (and (match_code "symbol_ref") - (match_test "!aarch64_is_noplt_call_p (op)"))) + (match_test "!(aarch64_is_noplt_call_p (op) + || aarch64_is_long_call_p (op))"))) (define_constraint "UsM" "@internal