Since patch_area_size and patch_area_entry have been added to cfun, we can use them to directly insert the pseudo UNSPECV_PATCHABLE_AREA instruction.
PR target/93492 * config/i386/i386-features.c (rest_of_insert_endbr_and_patchable_area): Change need_patchable_area argument to patchable_area_size. Generate UNSPECV_PATCHABLE_AREA instruction with proper arguments. (pass_insert_endbr_and_patchable_area::gate): Set and check patchable_area_size instead of need_patchable_area. (pass_insert_endbr_and_patchable_area::execute): Pass patchable_area_size to rest_of_insert_endbr_and_patchable_area. (pass_insert_endbr_and_patchable_area): Replace need_patchable_area with patchable_area_size. * config/i386/i386.c (ix86_print_patchable_function_entry): Just return if function table has been emitted. (x86_function_profiler): Use cfun->patch_area_size and cfun->patch_area_entry. * config/i386/i386.h (machine_function): Remove patch_area_size and record_patch_area. * config/i386/i386.md (patchable_area): Set length attribute. --- gcc/config/i386/i386-features.c | 22 +++++------- gcc/config/i386/i386.c | 60 ++++++--------------------------- gcc/config/i386/i386.h | 6 ---- gcc/config/i386/i386.md | 10 +++--- 4 files changed, 25 insertions(+), 73 deletions(-) diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c index be46f036126..d358abe7064 100644 --- a/gcc/config/i386/i386-features.c +++ b/gcc/config/i386/i386-features.c @@ -1941,7 +1941,7 @@ make_pass_stv (gcc::context *ctxt) static void rest_of_insert_endbr_and_patchable_area (bool need_endbr, - bool need_patchable_area) + unsigned int patchable_area_size) { rtx endbr; rtx_insn *insn; @@ -1980,7 +1980,7 @@ rest_of_insert_endbr_and_patchable_area (bool need_endbr, } } - if (need_patchable_area) + if (patchable_area_size) { if (crtl->profile && flag_fentry) { @@ -1992,10 +1992,9 @@ rest_of_insert_endbr_and_patchable_area (bool need_endbr, } else { - /* ix86_print_patchable_function_entry will provide actual - size. */ - rtx patchable_area = gen_patchable_area (GEN_INT (0), - GEN_INT (0)); + rtx patchable_area + = gen_patchable_area (GEN_INT (patchable_area_size), + GEN_INT (cfun->patch_area_entry == 0)); if (endbr_insn) emit_insn_after (patchable_area, endbr_insn); else @@ -2123,25 +2122,22 @@ public: virtual bool gate (function *fun) { need_endbr = (flag_cf_protection & CF_BRANCH) != 0; - need_patchable_area - = (function_entry_patch_area_size - || lookup_attribute ("patchable_function_entry", - DECL_ATTRIBUTES (fun->decl))); - return need_endbr || need_patchable_area; + patchable_area_size = fun->patch_area_size - fun->patch_area_entry; + return need_endbr || patchable_area_size; } virtual unsigned int execute (function *) { timevar_push (TV_MACH_DEP); rest_of_insert_endbr_and_patchable_area (need_endbr, - need_patchable_area); + patchable_area_size); timevar_pop (TV_MACH_DEP); return 0; } private: bool need_endbr; - bool need_patchable_area; + unsigned int patchable_area_size; }; // class pass_insert_endbr_and_patchable_area } // anon namespace diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 051a1fcbdc2..79a8823f61e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -9130,53 +9130,11 @@ ix86_print_patchable_function_entry (FILE *file, { if (cfun->machine->function_label_emitted) { - /* The insert_endbr_and_patchable_area pass inserted a dummy - UNSPECV_PATCHABLE_AREA with 0 patchable area size. If the - patchable area is placed after the function label, we replace - 0 patchable area size with the real one. Otherwise, the - dummy UNSPECV_PATCHABLE_AREA will be ignored. */ - if (cfun->machine->insn_queued_at_entrance) - { - /* Record the patchable area. Both ENDBR and patchable area - will be inserted by x86_function_profiler later. */ - cfun->machine->patch_area_size = patch_area_size; - cfun->machine->record_patch_area = record_p; - return; - } - - /* We can have - - UNSPECV_NOP_ENDBR - UNSPECV_PATCHABLE_AREA - - or just - - UNSPECV_PATCHABLE_AREA - */ - rtx_insn *patchable_insn; - rtx_insn *insn = next_real_nondebug_insn (get_insns ()); - if (insn - && INSN_P (insn) - && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE - && XINT (PATTERN (insn), 1) == UNSPECV_NOP_ENDBR) - patchable_insn = next_real_nondebug_insn (insn); - else - patchable_insn = insn; - - if (patchable_insn && INSN_P (patchable_insn)) - { - /* Replace the dummy patchable area size with the real one. */ - rtx pattern = PATTERN (patchable_insn); - if (GET_CODE (pattern) == UNSPEC_VOLATILE - && XINT (pattern, 1) == UNSPECV_PATCHABLE_AREA) - { - XVECEXP (pattern, 0, 0) = GEN_INT (patch_area_size); - XVECEXP (pattern, 0, 1) = GEN_INT (record_p); - } - return; - } - - gcc_unreachable (); + /* 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, @@ -20232,9 +20190,11 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) { if (cfun->machine->insn_queued_at_entrance == TYPE_ENDBR) fprintf (file, "\t%s\n", TARGET_64BIT ? "endbr64" : "endbr32"); - if (cfun->machine->patch_area_size) - ix86_output_patchable_area (cfun->machine->patch_area_size, - cfun->machine->record_patch_area); + unsigned int patch_area_size + = cfun->patch_area_size - cfun->patch_area_entry; + if (patch_area_size) + ix86_output_patchable_area (patch_area_size, + cfun->patch_area_entry == 0); } const char *mcount_name = MCOUNT_NAME; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 7c8f0cd4c70..e63edf16bcc 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2774,12 +2774,6 @@ struct GTY(()) machine_function { structure. */ rtx split_stack_varargs_pointer; - /* The size of the patchable area at function entry. */ - unsigned int patch_area_size; - - /* If true, record patchable area at function entry. */ - BOOL_BITFIELD record_patch_area : 1; - /* This value is used for amd64 targets and specifies the current abi to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */ ENUM_BITFIELD(calling_abi) call_abi : 8; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 78c38d5704a..3b243048d81 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -21289,11 +21289,13 @@ (define_insn "patchable_area" UNSPECV_PATCHABLE_AREA)] "" { - if (INTVAL (operands[0])) - ix86_output_patchable_area (INTVAL (operands[0]), - INTVAL (operands[1]) != 0); + 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") -- 2.24.1