On 8/21/23 01:26, pan2...@intel.com wrote:
From: Pan Li <pan2...@intel.com>
We have EMIT hook in mode switching already, which will insert the
insn before in most cases. However, in some arch like RISC-V, it
requires the additional insn to be inserted after when meet a call.
|
| <- EMIT HOOK, insert the insn before.
+-----------+
| ptr->insn |
+-----------+
| <- EMIT_AFTER HOOK, insert the insn after.
|
Thus, this patch would like to add one optional EMIT_AFTER hook, which
will try to insert the emitted insn after. The end-user can either
implement this HOOK or leave it NULL as is.
If the backend ignore this optinal hook, there is no impact to the
original mode switching stuff. If the backend implement this optional
hook, the mode switching will try to insert the insn after. Please note
the EMIT_AFTER doen't have any impact to EMIT hook.
Passed both the regression and bootstrap test in x86.
Signed-off-by: Pan Li <pan2...@intel.com>
gcc/ChangeLog:
* doc/tm.texi: Add hook def and update the description.
* doc/tm.texi.in: Ditto.
* mode-switching.cc (optimize_mode_switching): Insert the
emitted insn after ptr->insn.
* target.def (insn): Define emit_after hook.
Not a full review. I think I need to know a bit more about why you need
these additional hooks.
Presumably you can't use the current ".emit" hook because it doesn't
give you access to the block or insn that you can then iterate on for
insertion on the outgoing edges?
@@ -831,6 +833,49 @@ optimize_mode_switching (void)
emit_insn_before (mode_set, ptr->insn_ptr);
}
+ if (targetm.mode_switching.emit_after)
+ {
+ if (control_flow_insn_p (ptr->insn_ptr)
+ && ptr->insn_ptr == BB_END (bb))
I'm not aware of a case where we can have an insn with control flow that
isn't the end of the block. So perhaps then that second conditional
into an assertion inside the true arm?
+ {
+ edge eg;
+ edge_iterator eg_iterator;
+
+ FOR_EACH_EDGE (eg, eg_iterator, bb->succs)
+ {
+ start_sequence ();
+ targetm.mode_switching.emit_after (entity_map[j],
+ ptr->mode, cur_mode, ptr->regs_live);
+ mode_set = get_insns ();
+ end_sequence ();
+
+ if (mode_set != NULL_RTX)
+ {
+ if (eg->flags & EDGE_ABNORMAL)
+ insert_insn_end_basic_block (mode_set, bb);
+ else
+ insert_insn_on_edge (mode_set, eg);
Is this really correct for EDGE_ABNORMAL? If the abnormal edge is
created by, say a nonlocal goto, exception handling, etc, then the insn
you insert at the end of the block will never be executed.
This is a classic problem with these classes of algorithms and I suspect
there's code elsewhere to deal with these cases.
Jeff