public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/c++-coroutines] x86: Add UNSPECV_PATCHABLE_AREA
@ 2020-06-12 18:45 Iain D Sandoe
0 siblings, 0 replies; only message in thread
From: Iain D Sandoe @ 2020-06-12 18:45 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:3dcea658c9e2ac84f0726e679fd7d3b14f9106f0
commit 3dcea658c9e2ac84f0726e679fd7d3b14f9106f0
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Mon Feb 3 10:22:57 2020 -0800
x86: Add UNSPECV_PATCHABLE_AREA
Currently patchable area is at the wrong place. It is placed immediately
after function label, before both .cfi_startproc and ENDBR. This patch
adds UNSPECV_PATCHABLE_AREA for pseudo patchable area instruction and
changes ENDBR insertion pass to also insert patchable area instruction.
TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY is defined to avoid placing
patchable area before .cfi_startproc and ENDBR.
gcc/
PR target/93492
* config/i386/i386-features.c (rest_of_insert_endbranch):
Renamed to ...
(rest_of_insert_endbr_and_patchable_area): Change return type
to void. Add need_endbr and patchable_area_size arguments.
Don't call timevar_push nor timevar_pop. Replace
endbr_queued_at_entrance with insn_queued_at_entrance. Insert
UNSPECV_PATCHABLE_AREA for patchable area.
(pass_data_insert_endbranch): Renamed to ...
(pass_data_insert_endbr_and_patchable_area): This. Change
pass name to endbr_and_patchable_area.
(pass_insert_endbranch): Renamed to ...
(pass_insert_endbr_and_patchable_area): This. Add need_endbr
and patchable_area_size;.
(pass_insert_endbr_and_patchable_area::gate): Set and check
need_endbr and patchable_area_size.
(pass_insert_endbr_and_patchable_area::execute): Call
timevar_push and timevar_pop. Pass need_endbr and
patchable_area_size to rest_of_insert_endbr_and_patchable_area.
(make_pass_insert_endbranch): Renamed to ...
(make_pass_insert_endbr_and_patchable_area): This.
* config/i386/i386-passes.def: Replace pass_insert_endbranch
with pass_insert_endbr_and_patchable_area.
* config/i386/i386-protos.h (ix86_output_patchable_area): New.
(make_pass_insert_endbranch): Renamed to ...
(make_pass_insert_endbr_and_patchable_area): This.
* config/i386/i386.c (ix86_asm_output_function_label): Set
function_label_emitted to true.
(ix86_print_patchable_function_entry): New function.
(ix86_output_patchable_area): Likewise.
(x86_function_profiler): Replace endbr_queued_at_entrance with
insn_queued_at_entrance. Generate ENDBR only for TYPE_ENDBR.
Call ix86_output_patchable_area to generate patchable area if
needed.
(TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY): New.
* config/i386/i386.h (queued_insn_type): New.
(machine_function): Add function_label_emitted. Replace
endbr_queued_at_entrance with insn_queued_at_entrance.
* config/i386/i386.md (UNSPECV_PATCHABLE_AREA): New.
(patchable_area): New.
gcc/testsuite/
PR target/93492
* gcc.target/i386/pr93492-1.c: New test.
* gcc.target/i386/pr93492-2.c: Likewise.
* gcc.target/i386/pr93492-3.c: Likewise.
* gcc.target/i386/pr93492-4.c: Likewise.
* gcc.target/i386/pr93492-5.c: Likewise.
Diff:
---
gcc/config/i386/i386-features.c | 142 +++++++++++++++++++-----------
gcc/config/i386/i386-passes.def | 2 +-
gcc/config/i386/i386-protos.h | 5 +-
gcc/config/i386/i386.c | 51 ++++++++++-
gcc/config/i386/i386.h | 14 ++-
gcc/config/i386/i386.md | 17 ++++
gcc/testsuite/gcc.target/i386/pr93492-1.c | 73 +++++++++++++++
gcc/testsuite/gcc.target/i386/pr93492-2.c | 12 +++
gcc/testsuite/gcc.target/i386/pr93492-3.c | 13 +++
gcc/testsuite/gcc.target/i386/pr93492-4.c | 11 +++
gcc/testsuite/gcc.target/i386/pr93492-5.c | 12 +++
11 files changed, 296 insertions(+), 56 deletions(-)
diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index b9b764c092a..535fc7e981d 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -1946,48 +1946,83 @@ make_pass_stv (gcc::context *ctxt)
return new pass_stv (ctxt);
}
-/* Inserting ENDBRANCH instructions. */
+/* Inserting ENDBR and pseudo patchable-area instructions. */
-static unsigned int
-rest_of_insert_endbranch (void)
+static void
+rest_of_insert_endbr_and_patchable_area (bool need_endbr,
+ unsigned int patchable_area_size)
{
- timevar_push (TV_MACH_DEP);
-
- rtx cet_eb;
+ rtx endbr;
rtx_insn *insn;
+ rtx_insn *endbr_insn = NULL;
basic_block bb;
- /* Currently emit EB if it's a tracking function, i.e. 'nocf_check' is
- absent among function attributes. Later an optimization will be
- introduced to make analysis if an address of a static function is
- taken. A static function whose address is not taken will get a
- nocf_check attribute. This will allow to reduce the number of EB. */
-
- if (!lookup_attribute ("nocf_check",
- TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
- && (!flag_manual_endbr
- || lookup_attribute ("cf_check",
- DECL_ATTRIBUTES (cfun->decl)))
- && (!cgraph_node::get (cfun->decl)->only_called_directly_p ()
- || ix86_cmodel == CM_LARGE
- || ix86_cmodel == CM_LARGE_PIC
- || flag_force_indirect_call
- || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
- && DECL_DLLIMPORT_P (cfun->decl))))
- {
- /* Queue ENDBR insertion to x86_function_profiler. */
+ if (need_endbr)
+ {
+ /* Currently emit EB if it's a tracking function, i.e. 'nocf_check'
+ is absent among function attributes. Later an optimization will
+ be introduced to make analysis if an address of a static function
+ is taken. A static function whose address is not taken will get
+ a nocf_check attribute. This will allow to reduce the number of
+ EB. */
+ if (!lookup_attribute ("nocf_check",
+ TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
+ && (!flag_manual_endbr
+ || lookup_attribute ("cf_check",
+ DECL_ATTRIBUTES (cfun->decl)))
+ && (!cgraph_node::get (cfun->decl)->only_called_directly_p ()
+ || ix86_cmodel == CM_LARGE
+ || ix86_cmodel == CM_LARGE_PIC
+ || flag_force_indirect_call
+ || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && DECL_DLLIMPORT_P (cfun->decl))))
+ {
+ if (crtl->profile && flag_fentry)
+ {
+ /* Queue ENDBR insertion to x86_function_profiler.
+ NB: Any patchable-area insn will be inserted after
+ ENDBR. */
+ cfun->machine->insn_queued_at_entrance = TYPE_ENDBR;
+ }
+ else
+ {
+ endbr = gen_nop_endbr ();
+ bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+ rtx_insn *insn = BB_HEAD (bb);
+ endbr_insn = emit_insn_before (endbr, insn);
+ }
+ }
+ }
+
+ if (patchable_area_size)
+ {
if (crtl->profile && flag_fentry)
- cfun->machine->endbr_queued_at_entrance = true;
+ {
+ /* Queue patchable-area insertion to x86_function_profiler.
+ NB: If there is a queued ENDBR, x86_function_profiler
+ will also handle patchable-area. */
+ if (!cfun->machine->insn_queued_at_entrance)
+ cfun->machine->insn_queued_at_entrance = TYPE_PATCHABLE_AREA;
+ }
else
{
- cet_eb = gen_nop_endbr ();
-
- bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
- insn = BB_HEAD (bb);
- emit_insn_before (cet_eb, insn);
+ rtx patchable_area
+ = gen_patchable_area (GEN_INT (patchable_area_size),
+ GEN_INT (crtl->patch_area_entry == 0));
+ if (endbr_insn)
+ emit_insn_after (patchable_area, endbr_insn);
+ else
+ {
+ bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+ insn = BB_HEAD (bb);
+ emit_insn_before (patchable_area, insn);
+ }
}
}
+ if (!need_endbr)
+ return;
+
bb = 0;
FOR_EACH_BB_FN (bb, cfun)
{
@@ -1996,7 +2031,6 @@ rest_of_insert_endbranch (void)
{
if (CALL_P (insn))
{
- bool need_endbr;
need_endbr = find_reg_note (insn, REG_SETJMP, NULL) != NULL;
if (!need_endbr && !SIBLING_CALL_P (insn))
{
@@ -2027,8 +2061,8 @@ rest_of_insert_endbranch (void)
/* Generate ENDBRANCH after CALL, which can return more than
twice, setjmp-like functions. */
- cet_eb = gen_nop_endbr ();
- emit_insn_after_setloc (cet_eb, insn, INSN_LOCATION (insn));
+ endbr = gen_nop_endbr ();
+ emit_insn_after_setloc (endbr, insn, INSN_LOCATION (insn));
continue;
}
@@ -2058,31 +2092,30 @@ rest_of_insert_endbranch (void)
dest_blk = e->dest;
insn = BB_HEAD (dest_blk);
gcc_assert (LABEL_P (insn));
- cet_eb = gen_nop_endbr ();
- emit_insn_after (cet_eb, insn);
+ endbr = gen_nop_endbr ();
+ emit_insn_after (endbr, insn);
}
continue;
}
if (LABEL_P (insn) && LABEL_PRESERVE_P (insn))
{
- cet_eb = gen_nop_endbr ();
- emit_insn_after (cet_eb, insn);
+ endbr = gen_nop_endbr ();
+ emit_insn_after (endbr, insn);
continue;
}
}
}
- timevar_pop (TV_MACH_DEP);
- return 0;
+ return;
}
namespace {
-const pass_data pass_data_insert_endbranch =
+const pass_data pass_data_insert_endbr_and_patchable_area =
{
RTL_PASS, /* type. */
- "cet", /* name. */
+ "endbr_and_patchable_area", /* name. */
OPTGROUP_NONE, /* optinfo_flags. */
TV_MACH_DEP, /* tv_id. */
0, /* properties_required. */
@@ -2092,32 +2125,41 @@ const pass_data pass_data_insert_endbranch =
0, /* todo_flags_finish. */
};
-class pass_insert_endbranch : public rtl_opt_pass
+class pass_insert_endbr_and_patchable_area : public rtl_opt_pass
{
public:
- pass_insert_endbranch (gcc::context *ctxt)
- : rtl_opt_pass (pass_data_insert_endbranch, ctxt)
+ pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_insert_endbr_and_patchable_area, ctxt)
{}
/* opt_pass methods: */
virtual bool gate (function *)
{
- return ((flag_cf_protection & CF_BRANCH));
+ need_endbr = (flag_cf_protection & CF_BRANCH) != 0;
+ patchable_area_size = crtl->patch_area_size - crtl->patch_area_entry;
+ return need_endbr || patchable_area_size;
}
virtual unsigned int execute (function *)
{
- return rest_of_insert_endbranch ();
+ timevar_push (TV_MACH_DEP);
+ rest_of_insert_endbr_and_patchable_area (need_endbr,
+ patchable_area_size);
+ timevar_pop (TV_MACH_DEP);
+ return 0;
}
-}; // class pass_insert_endbranch
+private:
+ bool need_endbr;
+ unsigned int patchable_area_size;
+}; // class pass_insert_endbr_and_patchable_area
} // anon namespace
rtl_opt_pass *
-make_pass_insert_endbranch (gcc::context *ctxt)
+make_pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
{
- return new pass_insert_endbranch (ctxt);
+ return new pass_insert_endbr_and_patchable_area (ctxt);
}
/* At entry of the nearest common dominator for basic blocks with
diff --git a/gcc/config/i386/i386-passes.def b/gcc/config/i386/i386-passes.def
index 41386a13d88..d83c7b956b1 100644
--- a/gcc/config/i386/i386-passes.def
+++ b/gcc/config/i386/i386-passes.def
@@ -30,6 +30,6 @@ along with GCC; see the file COPYING3. If not see
CONSTM1_RTX generated by the STV pass can be CSEed. */
INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */);
- INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbranch);
+ INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbr_and_patchable_area);
INSERT_PASS_AFTER (pass_combine, 1, pass_remove_partial_avx_dependency);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 39fcaa0ad5f..e5574496bb7 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -89,6 +89,8 @@ extern const char *output_fp_compare (rtx_insn *, rtx*, bool, bool);
extern const char *output_adjust_stack_and_probe (rtx);
extern const char *output_probe_stack_range (rtx, rtx);
+extern void ix86_output_patchable_area (unsigned int, bool);
+
extern void ix86_expand_clear (rtx);
extern void ix86_expand_move (machine_mode, rtx[]);
extern void ix86_expand_vector_move (machine_mode, rtx[]);
@@ -378,6 +380,7 @@ class rtl_opt_pass;
extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *);
extern rtl_opt_pass *make_pass_stv (gcc::context *);
-extern rtl_opt_pass *make_pass_insert_endbranch (gcc::context *);
+extern rtl_opt_pass *make_pass_insert_endbr_and_patchable_area
+ (gcc::context *);
extern rtl_opt_pass *make_pass_remove_partial_avx_dependency
(gcc::context *);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 060e2df62ea..3b776c08a22 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1562,6 +1562,9 @@ ix86_asm_output_function_label (FILE *asm_out_file, const char *fname,
{
bool is_ms_hook = ix86_function_ms_hook_prologue (decl);
+ if (cfun)
+ cfun->machine->function_label_emitted = true;
+
if (is_ms_hook)
{
int i, filler_count = (TARGET_64BIT ? 32 : 16);
@@ -9367,6 +9370,38 @@ ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED)
}
}
+/* Implement TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY. */
+
+void
+ix86_print_patchable_function_entry (FILE *file,
+ unsigned HOST_WIDE_INT patch_area_size,
+ bool record_p)
+{
+ if (cfun->machine->function_label_emitted)
+ {
+ /* NB: When ix86_print_patchable_function_entry is called after
+ function table has been emitted, we have inserted or queued
+ a pseudo UNSPECV_PATCHABLE_AREA instruction at the proper
+ place. There is nothing to do here. */
+ return;
+ }
+
+ default_print_patchable_function_entry (file, patch_area_size,
+ record_p);
+}
+
+/* Output patchable area. NB: default_print_patchable_function_entry
+ isn't available in i386.md. */
+
+void
+ix86_output_patchable_area (unsigned int patch_area_size,
+ bool record_p)
+{
+ default_print_patchable_function_entry (asm_out_file,
+ patch_area_size,
+ record_p);
+}
+
/* Return a scratch register to use in the split stack prologue. The
split stack prologue is used for -fsplit-stack. It is the first
instructions in the function, even before the regular prologue.
@@ -20418,8 +20453,16 @@ current_fentry_section (const char **name)
void
x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
{
- if (cfun->machine->endbr_queued_at_entrance)
- fprintf (file, "\t%s\n", TARGET_64BIT ? "endbr64" : "endbr32");
+ if (cfun->machine->insn_queued_at_entrance)
+ {
+ if (cfun->machine->insn_queued_at_entrance == TYPE_ENDBR)
+ fprintf (file, "\t%s\n", TARGET_64BIT ? "endbr64" : "endbr32");
+ unsigned int patch_area_size
+ = crtl->patch_area_size - crtl->patch_area_entry;
+ if (patch_area_size)
+ ix86_output_patchable_area (patch_area_size,
+ crtl->patch_area_entry == 0);
+ }
const char *mcount_name = MCOUNT_NAME;
@@ -23019,6 +23062,10 @@ ix86_run_selftests (void)
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
+#undef TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY
+#define TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY \
+ ix86_print_patchable_function_entry
+
#undef TARGET_ENCODE_SECTION_INFO
#ifndef SUBTARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO ix86_encode_section_info
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 5bae257b435..5d0ea16a0bb 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2761,6 +2761,13 @@ enum function_type
TYPE_EXCEPTION
};
+enum queued_insn_type
+{
+ TYPE_NONE = 0,
+ TYPE_ENDBR,
+ TYPE_PATCHABLE_AREA
+};
+
struct GTY(()) machine_function {
struct stack_local_entry *stack_locals;
int varargs_gpr_size;
@@ -2851,8 +2858,11 @@ struct GTY(()) machine_function {
/* Nonzero if the function places outgoing arguments on stack. */
BOOL_BITFIELD outgoing_args_on_stack : 1;
- /* If true, ENDBR is queued at function entrance. */
- BOOL_BITFIELD endbr_queued_at_entrance : 1;
+ /* If true, ENDBR or patchable area is queued at function entrance. */
+ ENUM_BITFIELD(queued_insn_type) insn_queued_at_entrance : 2;
+
+ /* If true, the function label has been emitted. */
+ BOOL_BITFIELD function_label_emitted : 1;
/* True if the function needs a stack frame. */
BOOL_BITFIELD stack_frame_required : 1;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 9db7469dfcc..4d455584f09 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -307,6 +307,9 @@
;; For SERIALIZE support
UNSPECV_SERIALIZE
+
+ ;; For patchable area support
+ UNSPECV_PATCHABLE_AREA
])
;; Constants to represent rounding modes in the ROUND instruction
@@ -21529,6 +21532,20 @@
[(set_attr "type" "other")
(set_attr "length" "3")])
+(define_insn "patchable_area"
+ [(unspec_volatile [(match_operand 0 "const_int_operand")
+ (match_operand 1 "const_int_operand")]
+ UNSPECV_PATCHABLE_AREA)]
+ ""
+{
+ ix86_output_patchable_area (INTVAL (operands[0]),
+ INTVAL (operands[1]) != 0);
+ return "";
+}
+ [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))
+ (set_attr "length_immediate" "0")
+ (set_attr "modrm" "0")])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-1.c b/gcc/testsuite/gcc.target/i386/pr93492-1.c
new file mode 100644
index 00000000000..f978d2e5220
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-1.c
@@ -0,0 +1,73 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1 -fcf-protection -mmanual-endbr" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Note: this test only checks the instructions in the function bodies,
+ not the placement of the patch label or nops before the function. */
+
+/*
+**f10_none:
+** nop
+** ret
+*/
+void
+__attribute__ ((nocf_check,patchable_function_entry (1, 0)))
+f10_none (void)
+{
+}
+
+/*
+**f10_endbr:
+** endbr(32|64)
+** nop
+** ret
+*/
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 0)))
+f10_endbr (void)
+{
+}
+
+/*
+**f11_none:
+** ret
+*/
+void
+__attribute__ ((nocf_check,patchable_function_entry (1, 1)))
+f11_none (void)
+{
+}
+
+/*
+**f11_endbr:
+** endbr(32|64)
+** ret
+*/
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 1)))
+f11_endbr (void)
+{
+}
+
+/*
+**f21_none:
+** nop
+** ret
+*/
+void
+__attribute__ ((nocf_check,patchable_function_entry (2, 1)))
+f21_none (void)
+{
+}
+
+/*
+**f21_endbr:
+** endbr(32|64)
+** nop
+** ret
+*/
+void
+__attribute__ ((cf_check,patchable_function_entry (2, 1)))
+f21_endbr (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-2.c b/gcc/testsuite/gcc.target/i386/pr93492-2.c
new file mode 100644
index 00000000000..ec26d4cc367
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-2.c
@@ -0,0 +1,12 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1 -fcf-protection -mmanual-endbr -fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label. */
+
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 0)))
+f10_endbr (void)
+{
+}
+
+/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n.*\.LPFE1:\n\tnop\n\tret\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-3.c b/gcc/testsuite/gcc.target/i386/pr93492-3.c
new file mode 100644
index 00000000000..1f03c627120
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-3.c
@@ -0,0 +1,13 @@
+/* { dg-do "compile" } */
+/* { dg-require-effective-target mfentry } */
+/* { dg-options "-O1 -fcf-protection -mmanual-endbr -mfentry -pg -fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label. */
+
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 0)))
+f10_endbr (void)
+{
+}
+
+/* { dg-final { scan-assembler "\t\.cfi_startproc\n\tendbr(32|64)\n.*\.LPFE1:\n\tnop\n1:\tcall\t__fentry__\n\tret\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-4.c b/gcc/testsuite/gcc.target/i386/pr93492-4.c
new file mode 100644
index 00000000000..d193df8e66d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-4.c
@@ -0,0 +1,11 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1 -fpatchable-function-entry=1 -fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label. */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "\t\.cfi_startproc\n.*\.LPFE1:\n\tnop\n\tret\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-5.c b/gcc/testsuite/gcc.target/i386/pr93492-5.c
new file mode 100644
index 00000000000..d04077c6007
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-5.c
@@ -0,0 +1,12 @@
+/* { dg-do "compile" } */
+/* { dg-require-effective-target mfentry } */
+/* { dg-options "-O1 -fpatchable-function-entry=1 -mfentry -pg -fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label. */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "\t\.cfi_startproc\n.*\.LPFE1:\n\tnop\n1:\tcall\t__fentry__\n\tret\n" } } */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-06-12 18:45 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-12 18:45 [gcc/devel/c++-coroutines] x86: Add UNSPECV_PATCHABLE_AREA Iain D Sandoe
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).