On 24-04-14 17:13, Eric Botcazou wrote:
The hook is called right after expansion of calls, and allows a target to do
additional processing, such as f.i. adding clobbers to
CALL_INSN_FUNCTION_USAGE.
Instead of using the hook, we could add code to the preparation statements
operand of the different call expands, but that requires those expands not
to use the rtl template, and generate all the rtl through c code. Which
requires a rewrite of the call expands in case of Aarch64.
If Aarch64 is the only problematic back-end, then it should be changed to do
what the other back-ends already do to use use_reg. IMO adding such a bogus
hook should be the very last resort solution.
Eric,
I've written this concept patch, which tries to address the same problem, but in
a different (and I hope more generic) way.
It adds a post-emission C-code operand to define_expand.
As an example of how this could be useful, for the define_expand of call and
call_value in the arm target, I'm using the new operand to do the post-emit call
processing done currently in arm_emit_call_insn. This allows us to eliminate the
call_internal and call_value_internal define_expands, and simplifies the call
and call_value define_expands.
Any comments?
Thanks,
- Tom
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 74645ee..506791a 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -126,7 +126,7 @@ extern int arm_const_double_inline_cost (rtx);
extern bool arm_const_double_by_parts (rtx);
extern bool arm_const_double_by_immediates (rtx);
extern const char *fp_immediate_constant (rtx);
-extern void arm_emit_call_insn (rtx, rtx);
+extern void arm_post_emit_call_insn (rtx, rtx);
extern const char *output_call (rtx *);
extern const char *output_call_mem (rtx *);
void arm_emit_movpair (rtx, rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 09b5c52..e36deac 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -17602,16 +17602,14 @@ vfp_emit_fstmd (int base_reg, int count)
return count * 8;
}
-/* Emit a call instruction with pattern PAT. ADDR is the address of
- the call target. */
+/* Process a call instruction with pattern PAT after emission. ADDR is the
+ address of the call target. */
void
-arm_emit_call_insn (rtx pat, rtx addr)
+arm_post_emit_call_insn (rtx pat, rtx addr)
{
rtx insn;
- insn = emit_call_insn (pat);
-
/* The PIC register is live on entry to VxWorks PIC PLT entries.
If the call might use such an entry, add a use of the PIC register
to the instruction's CALL_INSN_FUNCTION_USAGE. */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 8a949b9..45019ae 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -9082,7 +9082,7 @@
"TARGET_EITHER"
"
{
- rtx callee, pat;
+ rtx callee;
/* In an untyped call, we can get NULL for operand 2. */
if (operands[2] == NULL_RTX)
@@ -9097,18 +9097,13 @@
: !REG_P (callee))
XEXP (operands[0], 0) = force_reg (Pmode, callee);
- pat = gen_call_internal (operands[0], operands[1], operands[2]);
- arm_emit_call_insn (pat, XEXP (operands[0], 0));
- DONE;
+ }"
+ []
+ "{
+ arm_post_emit_call_insn (_val, XEXP (operands[0], 0));
}"
)
-(define_expand "call_internal"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
- (use (match_operand 2 "" ""))
- (clobber (reg:SI LR_REGNUM))])])
-
(define_insn "*call_reg_armv5"
[(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
(match_operand 1 "" ""))
@@ -9191,7 +9186,7 @@
"TARGET_EITHER"
"
{
- rtx pat, callee;
+ rtx callee;
/* In an untyped call, we can get NULL for operand 2. */
if (operands[3] == 0)
@@ -9205,21 +9200,13 @@
? arm_is_long_call_p (SYMBOL_REF_DECL (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]);
- arm_emit_call_insn (pat, XEXP (operands[1], 0));
- DONE;
+ }"
+ []
+ "{
+ arm_post_emit_call_insn (_val, XEXP (operands[1], 0));
}"
)
-(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:SI LR_REGNUM))])])
-
(define_insn "*call_value_reg_armv5"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
diff --git a/gcc/genemit.c b/gcc/genemit.c
index faaa610..aff27f6 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -422,7 +422,8 @@ gen_expand (rtx expand)
/* If we don't have any C code to write, only one insn is being written,
and no MATCH_DUPs are present, we can just return the desired insn
like we do for a DEFINE_INSN. This saves memory. */
- if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
+ if (((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0'))
+ && (XSTR (expand, 5) == 0 || *XSTR (expand, 5) == '\0')
&& stats.max_opno >= stats.max_dup_opno
&& XVECLEN (expand, 1) == 1)
{
@@ -525,6 +526,23 @@ gen_expand (rtx expand)
printf (" _val = get_insns ();\n");
printf (" end_sequence ();\n");
+
+ if (XSTR (expand, 5) && *XSTR (expand, 5))
+ {
+ printf (" {\n");
+ if (stats.num_operand_vars > 0)
+ printf (" rtx operands[%d];\n", stats.num_operand_vars);
+
+ /* Output code to copy the arguments into `operands'. */
+ for (i = 0; i < stats.num_generator_args; i++)
+ printf (" operands[%d] = operand%d;\n", i, i);
+
+ print_md_ptr_loc (XSTR (expand, 5));
+ printf ("%s\n", XSTR (expand, 5));
+
+ printf (" }\n");
+ }
+
printf (" return _val;\n}\n\n");
}
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 56418c7..655f752 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -933,8 +933,10 @@ DEF_RTL_EXPR(DEFINE_PEEPHOLE2, "define_peephole2", "EsES", RTX_EXTRA)
elements of `recog_data.operand' for use by the vector of
insn-patterns.
(`operands' is an alias here for `recog_data.operand').
- 5th: optionally, a vector of attributes for this expand. */
-DEF_RTL_EXPR(DEFINE_EXPAND, "define_expand", "sEssV", RTX_EXTRA)
+ 5th: optionally, a vector of attributes for this expand.
+ 6th operand: Extra C code to execute after generating the insns. This code
+ is not executed if DONE (or FAIL) is used in the 4th operand. */
+DEF_RTL_EXPR(DEFINE_EXPAND, "define_expand", "sEssVs", RTX_EXTRA)
/* Define a requirement for delay slots.
1st operand: Condition involving insn attributes that, if true,
--
1.8.3.2