* [PATCH][AARCH64]Simplify call, call_value, sibcall, sibcall_value patterns.
@ 2016-12-01 15:40 Renlin Li
2017-05-02 13:02 ` Richard Earnshaw (lists)
0 siblings, 1 reply; 3+ messages in thread
From: Renlin Li @ 2016-12-01 15:40 UTC (permalink / raw)
To: gcc-patches, James Greenhalgh, Richard Henderson, Wilco Dijkstra,
Ramana Radhakrishnan
[-- Attachment #1: Type: text/plain, Size: 1813 bytes --]
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 <renlin.li@arm.com>
* 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.
[-- Attachment #2: new.diff --]
[-- Type: text/x-patch, Size: 9497 bytes --]
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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH][AARCH64]Simplify call, call_value, sibcall, sibcall_value patterns.
2016-12-01 15:40 [PATCH][AARCH64]Simplify call, call_value, sibcall, sibcall_value patterns Renlin Li
@ 2017-05-02 13:02 ` Richard Earnshaw (lists)
2017-05-15 11:33 ` Renlin Li
0 siblings, 1 reply; 3+ messages in thread
From: Richard Earnshaw (lists) @ 2017-05-02 13:02 UTC (permalink / raw)
To: Renlin Li, gcc-patches, James Greenhalgh, Richard Henderson,
Wilco Dijkstra, Ramana Radhakrishnan
On 01/12/16 15:39, Renlin Li wrote:
> 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 <renlin.li@arm.com>
>
> * 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.
>
>
> new.diff
>
>
> 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
Drop '64-bit'. This code should also work for ILP32, where the
addresses are 32-bit.
> + the branch-and-link. */
> +
> + if (GET_CODE (callee) == SYMBOL_REF
Use SYMBOL_REF_P.
OK with those changes.
R.
> + ? (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
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH][AARCH64]Simplify call, call_value, sibcall, sibcall_value patterns.
2017-05-02 13:02 ` Richard Earnshaw (lists)
@ 2017-05-15 11:33 ` Renlin Li
0 siblings, 0 replies; 3+ messages in thread
From: Renlin Li @ 2017-05-15 11:33 UTC (permalink / raw)
To: Richard Earnshaw (lists),
gcc-patches, James Greenhalgh, Richard Henderson, Wilco Dijkstra,
Ramana Radhakrishnan
Hi Richard,
Thanks! committed with all the comments resolved.
Regards,
Renlin
On 02/05/17 13:53, Richard Earnshaw (lists) wrote:
> On 01/12/16 15:39, Renlin Li wrote:
>> 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 <renlin.li@arm.com>
>>
>> * 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.
>>
>>
>> new.diff
>>
>>
>> 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
>
> Drop '64-bit'. This code should also work for ILP32, where the
> addresses are 32-bit.
>
>> + the branch-and-link. */
>> +
>> + if (GET_CODE (callee) == SYMBOL_REF
>
> Use SYMBOL_REF_P.
>
> OK with those changes.
>
> R.
>
>
>> + ? (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
>>
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-05-15 11:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-01 15:40 [PATCH][AARCH64]Simplify call, call_value, sibcall, sibcall_value patterns Renlin Li
2017-05-02 13:02 ` Richard Earnshaw (lists)
2017-05-15 11:33 ` Renlin Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).