[gcc r15-1564] tree-optimization/115579 - fix wrong code with store-motion
https://gcc.gnu.org/g:8a1795bddcd34284936af4706f762d89c60fc69c commit r15-1564-g8a1795bddcd34284936af4706f762d89c60fc69c Author: Richard Biener Date: Sat Jun 22 14:59:09 2024 +0200 tree-optimization/115579 - fix wrong code with store-motion The recent change to relax store motion for variables that cannot have store data races broke the optimization to share flag vars for stores that all happen in the same single BB. The following fixes this. PR tree-optimization/115579 * tree-ssa-loop-im.cc (execute_sm): Return the auxiliary data created. (hoist_memory_references): Record the flag var that's eventually created and re-use it when all stores are in the same BB. * gcc.dg/pr115579.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/pr115579.c | 18 ++ gcc/tree-ssa-loop-im.cc | 27 ++- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/gcc/testsuite/gcc.dg/pr115579.c b/gcc/testsuite/gcc.dg/pr115579.c new file mode 100644 index 000..04781056723 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr115579.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-options "-Os -fno-tree-sra" } */ + +int printf(const char *, ...); +int a, b = 1, c; +int main() { + int d[2], *e = &d[1]; + while (a) { +int *f = &b; +d[1] = 0; +*f = 0; + } + if (c) +printf("%d\n", *e); + if (b != 1) +__builtin_abort(); + return 0; +} diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc index 3acbd886a0d..61c6339bc35 100644 --- a/gcc/tree-ssa-loop-im.cc +++ b/gcc/tree-ssa-loop-im.cc @@ -2269,7 +2269,7 @@ struct sm_aux temporary variable is put to the preheader of the loop, and assignments to the reference from the temporary variable are emitted to exits. */ -static void +static sm_aux * execute_sm (class loop *loop, im_mem_ref *ref, hash_map &aux_map, bool maybe_mt, bool use_other_flag_var) @@ -2345,6 +2345,8 @@ execute_sm (class loop *loop, im_mem_ref *ref, lim_data->tgt_loop = loop; gsi_insert_before (&gsi, load, GSI_SAME_STMT); } + + return aux; } /* sm_ord is used for ordinary stores we can retain order with respect @@ -2802,20 +2804,18 @@ hoist_memory_references (class loop *loop, bitmap mem_refs, hash_map aux_map; /* Execute SM but delay the store materialization for ordered -sequences on exit. */ - bool first_p = true; +sequences on exit. Remember a created flag var and make +sure to re-use it. */ + sm_aux *flag_var_aux = nullptr; EXECUTE_IF_SET_IN_BITMAP (mem_refs, 0, i, bi) { ref = memory_accesses.refs_list[i]; - execute_sm (loop, ref, aux_map, true, !first_p); - first_p = false; + sm_aux *aux = execute_sm (loop, ref, aux_map, true, + flag_var_aux != nullptr); + if (aux->store_flag) + flag_var_aux = aux; } - /* Get at the single flag variable we eventually produced. */ - im_mem_ref *ref - = memory_accesses.refs_list[bitmap_first_set_bit (mem_refs)]; - sm_aux *aux = *aux_map.get (ref); - /* Materialize ordered store sequences on exits. */ edge e; FOR_EACH_VEC_ELT (exits, i, e) @@ -2826,13 +2826,14 @@ hoist_memory_references (class loop *loop, bitmap mem_refs, /* Construct the single flag variable control flow and insert the ordered seq of stores in the then block. With -fstore-data-races we can do the stores unconditionally. */ - if (aux->store_flag) + if (flag_var_aux) insert_e = single_pred_edge (execute_sm_if_changed (e, NULL_TREE, NULL_TREE, - aux->store_flag, + flag_var_aux->store_flag, loop_preheader_edge (loop), - &aux->flag_bbs, append_cond_position, + &flag_var_aux->flag_bbs, + append_cond_position, last_cond_fallthru)); execute_sm_exit (loop, insert_e, seq, aux_map, sm_ord, append_cond_position, last_cond_fallthru);
[gcc r15-1565] tree-optimization/115597 - allow CSE of two-operator VEC_PERM nodes
https://gcc.gnu.org/g:2a345214fc332b6f0821edf394ff8802b768db1d commit r15-1565-g2a345214fc332b6f0821edf394ff8802b768db1d Author: Richard Biener Date: Sun Jun 23 11:26:39 2024 +0200 tree-optimization/115597 - allow CSE of two-operator VEC_PERM nodes The following makes sure to always CSE when there's SLP_TREE_SCALAR_STMTS as otherwise a chain of two-operator node operations can result in exponential behavior of the CSE process as likely seen when building 510.parest on aarch64. PR tree-optimization/115597 * tree-vect-slp.cc (vect_cse_slp_nodes): Allow to CSE VEC_PERM nodes. Diff: --- gcc/tree-vect-slp.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 4935cf9e521..e84aeabef94 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -6080,7 +6080,6 @@ static void vect_cse_slp_nodes (scalar_stmts_to_slp_tree_map_t *bst_map, slp_tree& node) { if (SLP_TREE_DEF_TYPE (node) == vect_internal_def - && SLP_TREE_CODE (node) != VEC_PERM_EXPR /* Besides some VEC_PERM_EXPR, two-operator nodes also lack scalar stmts and thus CSE doesn't work via bst_map. Ideally we'd have sth that works for all internal and external nodes. */
[gcc r15-1566] [committed][RISC-V][PR target/114139] Verify we have a CONST_INT before extracting INTVAL
https://gcc.gnu.org/g:fd536b8412d4dae42aa04739c06f99a915be6261 commit r15-1566-gfd536b8412d4dae42aa04739c06f99a915be6261 Author: Jeff Law Date: Sun Jun 23 08:26:25 2024 -0600 [committed][RISC-V][PR target/114139] Verify we have a CONST_INT before extracting INTVAL Run-of-the-mill checking issue. We had something like (plus (reg) (reg)) and tried to extract INTVAL (XEXP (x, 1)) which of course blows up with checking on. Fixed thusly. Tested on riscv32-elf in my tester. riscv64-elf is in flight, but won't finish for a while due to other tasks in flight. PR target/114139 gcc/ * config/riscv/riscv.cc (riscv_macro_fusion_pair_p): Verify object is a CONST_INT before looking at INTVAL. gcc/testsuite/ * gcc.target/riscv/pr114139.c: New test. Diff: --- gcc/config/riscv/riscv.cc | 1 + gcc/testsuite/gcc.target/riscv/pr114139.c | 27 +++ 2 files changed, 28 insertions(+) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index c17141d909a..5c758b95327 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -9242,6 +9242,7 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) && XINT (SET_SRC (prev_set), 1) == UNSPEC_AUIPC && (GET_CODE (SET_SRC (curr_set)) == LO_SUM || (GET_CODE (SET_SRC (curr_set)) == PLUS + && CONST_INT_P (XEXP (SET_SRC (curr_set), 1)) && SMALL_OPERAND (INTVAL (XEXP (SET_SRC (curr_set), 1)) return true; diff --git a/gcc/testsuite/gcc.target/riscv/pr114139.c b/gcc/testsuite/gcc.target/riscv/pr114139.c new file mode 100644 index 000..1d4eeb65f5c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr114139.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fpic -mexplicit-relocs -mcpu=sifive-p450" } */ + +static void *p; +extern void *a[]; +void +baz (void) +{ + p = 0; +} + +void bar (void); +void +foo (int i) +{ + bar (); + a[i] = p; +} + + +double *d; +void +foobar (int i) +{ + for (; i; ++i) +d[i] = 1; +}
[gcc r15-1567] [PATCH] RISC-V: Fix unrecognizable pattern in riscv_expand_conditional_move()
https://gcc.gnu.org/g:eb647daa87b466d0a71246fad302cd81bfce9be5 commit r15-1567-geb647daa87b466d0a71246fad302cd81bfce9be5 Author: Artemiy Volkov Date: Sun Jun 23 14:54:00 2024 -0600 [PATCH] RISC-V: Fix unrecognizable pattern in riscv_expand_conditional_move() Presently, the code fragment: int x[5]; void d(int a, int b, int c) { for (int i = 0; i < 5; i++) x[i] = (a != b) ? c : a; } causes an ICE when compiled with -O2 -march=rv32i_zicond: test.c: In function 'd': test.c: error: unrecognizable insn: 11 | } | ^ (insn 8 5 9 2 (set (reg:SI 139 [ iftmp.0_2 ]) (if_then_else:SI (ne:SI (reg/v:SI 136 [ a ]) (reg/v:SI 137 [ b ])) (reg/v:SI 136 [ a ]) (reg/v:SI 138 [ c ]))) -1 (nil)) during RTL pass: vregs This happens because, as part of one of the optimizations in riscv_expand_conditional_move(), an if_then_else is generated with both comparands being register operands, resulting in an unmatchable insn since Zicond patterns require constant 0 as the second comparand. Fix this by adding a extra check before performing this optimization. The code snippet mentioned above is also included in this patch as a new Zicond testcase. gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Add a CONST0_RTX check. gcc/testsuite/ChangeLog: * gcc.target/riscv/zicond-ice-5.c: New test. Diff: --- gcc/config/riscv/riscv.cc | 3 ++- gcc/testsuite/gcc.target/riscv/zicond-ice-5.c | 11 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 5c758b95327..cca7ffde33a 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -5111,8 +5111,9 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) /* reg, reg */ else if (REG_P (cons) && REG_P (alt)) { - if ((code == EQ && rtx_equal_p (cons, op0)) + if (((code == EQ && rtx_equal_p (cons, op0)) || (code == NE && rtx_equal_p (alt, op0))) + && op1 == CONST0_RTX (mode)) { rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); alt = force_reg (mode, alt); diff --git a/gcc/testsuite/gcc.target/riscv/zicond-ice-5.c b/gcc/testsuite/gcc.target/riscv/zicond-ice-5.c new file mode 100644 index 000..ac6049c9ae5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zicond-ice-5.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ + +int x[5]; + +void +d(int a, int b, int c) { + for (int i = 0; i < 5; i++) +x[i] = (a != b) ? c : a; +}
[gcc r15-1568] [PATCH 01/11] Output CodeView data about variables
https://gcc.gnu.org/g:a9df6bdef485a185a0911d103e7a456c2f22c16a commit r15-1568-ga9df6bdef485a185a0911d103e7a456c2f22c16a Author: Mark Harmstone Date: Sun Jun 23 17:48:10 2024 -0600 [PATCH 01/11] Output CodeView data about variables Parse the DW_TAG_variable DIEs, and outputs S_GDATA32 (for global variables) and S_LDATA32 (static global variables) symbols into the .debug$S section. gcc/ * dwarf2codeview.cc (S_LDATA32, S_GDATA32): Define. (struct codeview_symbol): New structure. (sym, last_sym): New variables. (write_data_symbol): New function. (write_codeview_symbols): Call write_data_symbol. (add_variable, codeview_debug_early_finish): New functions. * dwarf2codeview.h (codeview_debug_early_finish): Prototype. * dwarf2out.cc (dwarf2out_early_finish): Call codeview_debug_early_finish. Diff: --- gcc/dwarf2codeview.cc | 160 ++ gcc/dwarf2codeview.h | 1 + gcc/dwarf2out.cc | 5 ++ 3 files changed, 166 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index db776d79be4..60e84635971 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see #define CHKSUM_TYPE_MD51 +#define S_LDATA32 0x110c +#define S_GDATA32 0x110d #define S_COMPILE3 0x113c #define CV_CFL_80386 0x03 @@ -129,6 +131,22 @@ struct codeview_function codeview_line_block *blocks, *last_block; }; +struct codeview_symbol +{ + codeview_symbol *next; + uint16_t kind; + + union + { +struct +{ + uint32_t type; + char *name; + dw_die_ref die; +} data_symbol; + }; +}; + static unsigned int line_label_num; static unsigned int func_label_num; static unsigned int sym_label_num; @@ -140,6 +158,7 @@ static codeview_string *strings, *last_string; static codeview_function *funcs, *last_func; static const char* last_filename; static uint32_t last_file_id; +static codeview_symbol *sym, *last_sym; /* Record new line number against the current function. */ @@ -698,6 +717,77 @@ write_compile3_symbol (void) targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num); } +/* Write an S_GDATA32 symbol, representing a global variable, or an S_LDATA32 + symbol, for a static global variable. */ + +static void +write_data_symbol (codeview_symbol *s) +{ + unsigned int label_num = ++sym_label_num; + dw_attr_node *loc; + dw_loc_descr_ref loc_ref; + + /* This is struct datasym in binutils: + + struct datasym + { + uint16_t size; + uint16_t kind; + uint32_t type; + uint32_t offset; + uint16_t section; + char name[]; + } ATTRIBUTE_PACKED; + */ + + /* Extract the DW_AT_location attribute from the DIE, and make sure it's in + in a format we can parse. */ + + loc = get_AT (s->data_symbol.die, DW_AT_location); + if (!loc) +goto end; + + if (loc->dw_attr_val.val_class != dw_val_class_loc) +goto end; + + loc_ref = loc->dw_attr_val.v.val_loc; + if (!loc_ref || loc_ref->dw_loc_opc != DW_OP_addr) +goto end; + + /* Output the S_GDATA32 / S_LDATA32 record. */ + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, + "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n", + label_num, label_num); + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, s->kind); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, s->data_symbol.type); + putc ('\n', asm_out_file); + + asm_fprintf (asm_out_file, "\t.secrel32 "); + output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr); + fputc ('\n', asm_out_file); + + asm_fprintf (asm_out_file, "\t.secidx "); + output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr); + fputc ('\n', asm_out_file); + + ASM_OUTPUT_ASCII (asm_out_file, s->data_symbol.name, + strlen (s->data_symbol.name) + 1); + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num); + +end: + free (s->data_symbol.name); +} + /* Write the CodeView symbols into the .debug$S section. */ static void @@ -714,6 +804,22 @@ write_codeview_symbols (void) write_compile3_symbol (); + while (sym) +{ + codeview_symbol *n = sym->next; + + switch (sym->kind) + { + case S_LDATA32: + case S_GDATA32: + write_data_symbol (sym); + break; + } + + free (sym); + sym = n; +} + asm_fprintf (asm_out_file, "%LLcv_syms_end:\n"); } @@ -734,4 +840,58 @@ codeview_debug_finish (void) write_codeview_symbols (); } +/* Process a DW_
[gcc r15-1570] [PATCH 02/11] Handle CodeView base types
https://gcc.gnu.org/g:340bca65ce50ccb827a2501273f50da77c7d7349 commit r15-1570-g340bca65ce50ccb827a2501273f50da77c7d7349 Author: Mark Harmstone Date: Sun Jun 23 18:17:39 2024 -0600 [PATCH 02/11] Handle CodeView base types Adds a get_type_num function to translate type DIEs into CodeView numbers, along with a hash table for this. For now we just deal with the base types (integers, Unicode chars, floats, and bools). gcc/ * dwarf2codeview.cc (struct codeview_type): New structure. (struct die_hasher): Likewise. (types_htab): New variable. (codeview_debug_finish): Free types_htab if allocated. (get_type_num_base_type, get_type_num): New function. (add_variable): Call get_type_num. * dwarf2codeview.h (T_CHAR, T_SHORT, T_LONG, T_QUAD): Define. (T_UCHAR, T_USHORT, T_ULONG, T_UQUAD, T_BOOL08): Likewise. (T_REAL32, T_REAL64, T_REAL80, T_REAL128, T_RCHAR): Likewise. (T_WCHAR, T_INT4, T_UINT4, T_CHAR16, T_CHAR32, T_CHAR8): Likewise. Diff: --- gcc/dwarf2codeview.cc | 196 +- gcc/dwarf2codeview.h | 23 ++ 2 files changed, 218 insertions(+), 1 deletion(-) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 60e84635971..eb7c1270e31 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -147,6 +147,27 @@ struct codeview_symbol }; }; +struct codeview_type +{ + dw_die_ref die; + uint32_t num; +}; + +struct die_hasher : free_ptr_hash +{ + typedef dw_die_ref compare_type; + + static hashval_t hash (const codeview_type *x) + { +return htab_hash_pointer (x->die); + } + + static bool equal (const codeview_type *x, const dw_die_ref y) + { +return x->die == y; + } +}; + static unsigned int line_label_num; static unsigned int func_label_num; static unsigned int sym_label_num; @@ -159,6 +180,7 @@ static codeview_function *funcs, *last_func; static const char* last_filename; static uint32_t last_file_id; static codeview_symbol *sym, *last_sym; +static hash_table *types_htab; /* Record new line number against the current function. */ @@ -838,6 +860,178 @@ codeview_debug_finish (void) write_source_files (); write_line_numbers (); write_codeview_symbols (); + + if (types_htab) +delete types_htab; +} + +/* Translate a DWARF base type (DW_TAG_base_type) into its CodeView + equivalent. */ + +static uint32_t +get_type_num_base_type (dw_die_ref type) +{ + unsigned int size = get_AT_unsigned (type, DW_AT_byte_size); + + switch (get_AT_unsigned (type, DW_AT_encoding)) +{ +case DW_ATE_signed_char: + { + const char *name = get_AT_string (type, DW_AT_name); + + if (size != 1) + return 0; + + if (name && !strcmp (name, "signed char")) + return T_CHAR; + else + return T_RCHAR; + } + +case DW_ATE_unsigned_char: + if (size != 1) + return 0; + + return T_UCHAR; + +case DW_ATE_signed: + switch (size) + { + case 2: + return T_SHORT; + + case 4: + { + const char *name = get_AT_string (type, DW_AT_name); + + if (name && !strcmp (name, "int")) + return T_INT4; + else + return T_LONG; + } + + case 8: + return T_QUAD; + + default: + return 0; + } + +case DW_ATE_unsigned: + switch (size) + { + case 2: + { + const char *name = get_AT_string (type, DW_AT_name); + + if (name && !strcmp (name, "wchar_t")) + return T_WCHAR; + else + return T_USHORT; + } + + case 4: + { + const char *name = get_AT_string (type, DW_AT_name); + + if (name && !strcmp (name, "unsigned int")) + return T_UINT4; + else + return T_ULONG; + } + + case 8: + return T_UQUAD; + + default: + return 0; + } + +case DW_ATE_UTF: + switch (size) + { + case 1: + return T_CHAR8; + + case 2: + return T_CHAR16; + + case 4: + return T_CHAR32; + + default: + return 0; + } + +case DW_ATE_float: + switch (size) + { + case 4: + return T_REAL32; + + case 8: + return T_REAL64; + + case 12: + return T_REAL80; + + case 16: + return T_REAL128; + + default: + return 0; + } + +case DW_ATE_boolean: + if (size == 1) + return T_BOOL08; + else + return 0; + +default: + return 0; +} +} + +/* Process a DIE representing a type definition and return its number. If + it's something we can't handle, return 0. We keep a hash table so that + we're not adding the same type multiple times - though if we do it's not +
[gcc r15-1571] [PATCH 03/11] Handle typedefs for CodeView
https://gcc.gnu.org/g:de2ade6908c6f18b821d6d25b4f4833c850fa19c commit r15-1571-gde2ade6908c6f18b821d6d25b4f4833c850fa19c Author: Mark Harmstone Date: Sun Jun 23 18:30:02 2024 -0600 [PATCH 03/11] Handle typedefs for CodeView gcc/ * dwarf2codeview.cc (get_type_num): Handle typedefs. Diff: --- gcc/dwarf2codeview.cc | 6 ++ 1 file changed, 6 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index eb7c1270e31..5006a176260 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -1024,6 +1024,12 @@ get_type_num (dw_die_ref type) t->num = get_type_num_base_type (type); break; +case DW_TAG_typedef: + /* FIXME - signed longs typedef'd as "HRESULT" should get their +own type (T_HRESULT) */ + t->num = get_type_num (get_AT_ref (type, DW_AT_type)); + break; + default: t->num = 0; break;
[gcc r14-10342] rs6000: Don't clobber return value when eh_return called [PR114846]
https://gcc.gnu.org/g:2b5e8f918ef0027d2af8e53c4e114e1d133fc609 commit r14-10342-g2b5e8f918ef0027d2af8e53c4e114e1d133fc609 Author: Kewen Lin Date: Tue May 28 21:13:40 2024 -0500 rs6000: Don't clobber return value when eh_return called [PR114846] As the associated test case in PR114846 shows, currently with eh_return involved some register restoring for EH RETURN DATA in epilogue can clobber the one which holding the return value. Referring to the existing handlings in some other targets, this patch makes eh_return expander call one new define_insn_and_split eh_return_internal which directly calls rs6000_emit_epilogue with epilogue_type EPILOGUE_TYPE_EH_RETURN instead of the previous treating normal return with crtl->calls_eh_return specially. PR target/114846 gcc/ChangeLog: * config/rs6000/rs6000-logue.cc (rs6000_emit_epilogue): As EPILOGUE_TYPE_EH_RETURN would be passed as epilogue_type directly now, adjust the relevant handlings on it. * config/rs6000/rs6000.md (eh_return expander): Append by calling gen_eh_return_internal and emit_barrier. (eh_return_internal): New define_insn_and_split, call function rs6000_emit_epilogue with epilogue type EPILOGUE_TYPE_EH_RETURN. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr114846.c: New test. (cherry picked from commit e5fc5d42d25c86ae48178db04ce64d340a834614) Diff: --- gcc/config/rs6000/rs6000-logue.cc | 7 +++ gcc/config/rs6000/rs6000.md | 15 +++ gcc/testsuite/gcc.target/powerpc/pr114846.c | 20 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index 60ba15a8bc3..bd5d56ba002 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -4308,9 +4308,6 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) rs6000_stack_t *info = rs6000_stack_info (); - if (epilogue_type == EPILOGUE_TYPE_NORMAL && crtl->calls_eh_return) -epilogue_type = EPILOGUE_TYPE_EH_RETURN; - int strategy = info->savres_strategy; bool using_load_multiple = !!(strategy & REST_MULTIPLE); bool restoring_GPRs_inline = !!(strategy & REST_INLINE_GPRS); @@ -4788,7 +4785,9 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) /* In the ELFv2 ABI we need to restore all call-saved CR fields from *separate* slots if the routine calls __builtin_eh_return, so - that they can be independently restored by the unwinder. */ + that they can be independently restored by the unwinder. Since + it is for CR fields restoring, it should be done for any epilogue + types (not EPILOGUE_TYPE_EH_RETURN specific). */ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return) { int i, cr_off = info->ehcr_offset; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index ac5651d7420..d4120c3b9ce 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -14281,6 +14281,8 @@ "" { emit_insn (gen_eh_set_lr (Pmode, operands[0])); + emit_jump_insn (gen_eh_return_internal ()); + emit_barrier (); DONE; }) @@ -14297,6 +14299,19 @@ DONE; }) +(define_insn_and_split "eh_return_internal" + [(eh_return)] + "" + "#" + "epilogue_completed" + [(const_int 0)] +{ + if (!TARGET_SCHED_PROLOG) +emit_insn (gen_blockage ()); + rs6000_emit_epilogue (EPILOGUE_TYPE_EH_RETURN); + DONE; +}) + (define_insn "prefetch" [(prefetch (match_operand 0 "indexed_or_indirect_address" "a") (match_operand:SI 1 "const_int_operand" "n") diff --git a/gcc/testsuite/gcc.target/powerpc/pr114846.c b/gcc/testsuite/gcc.target/powerpc/pr114846.c new file mode 100644 index 000..efe2300b73a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr114846.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target builtin_eh_return } */ + +/* Ensure it runs successfully. */ + +__attribute__ ((noipa)) +int f (int *a, long offset, void *handler) +{ + if (*a == 5) +return 5; + __builtin_eh_return (offset, handler); +} + +int main () +{ + int t = 5; + if (f (&t, 0, 0) != 5) +__builtin_abort (); + return 0; +}
[gcc r13-8866] rs6000: Don't clobber return value when eh_return called [PR114846]
https://gcc.gnu.org/g:dd54ed4ae417935300a3c4bb356d37c2ae7f731e commit r13-8866-gdd54ed4ae417935300a3c4bb356d37c2ae7f731e Author: Kewen Lin Date: Tue May 28 21:13:40 2024 -0500 rs6000: Don't clobber return value when eh_return called [PR114846] As the associated test case in PR114846 shows, currently with eh_return involved some register restoring for EH RETURN DATA in epilogue can clobber the one which holding the return value. Referring to the existing handlings in some other targets, this patch makes eh_return expander call one new define_insn_and_split eh_return_internal which directly calls rs6000_emit_epilogue with epilogue_type EPILOGUE_TYPE_EH_RETURN instead of the previous treating normal return with crtl->calls_eh_return specially. PR target/114846 gcc/ChangeLog: * config/rs6000/rs6000-logue.cc (rs6000_emit_epilogue): As EPILOGUE_TYPE_EH_RETURN would be passed as epilogue_type directly now, adjust the relevant handlings on it. * config/rs6000/rs6000.md (eh_return expander): Append by calling gen_eh_return_internal and emit_barrier. (eh_return_internal): New define_insn_and_split, call function rs6000_emit_epilogue with epilogue type EPILOGUE_TYPE_EH_RETURN. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr114846.c: New test. (cherry picked from commit e5fc5d42d25c86ae48178db04ce64d340a834614) Diff: --- gcc/config/rs6000/rs6000-logue.cc | 7 +++ gcc/config/rs6000/rs6000.md | 15 +++ gcc/testsuite/gcc.target/powerpc/pr114846.c | 20 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index d6c9c6e5b52..baadbbd692e 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -4311,9 +4311,6 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) rs6000_stack_t *info = rs6000_stack_info (); - if (epilogue_type == EPILOGUE_TYPE_NORMAL && crtl->calls_eh_return) -epilogue_type = EPILOGUE_TYPE_EH_RETURN; - int strategy = info->savres_strategy; bool using_load_multiple = !!(strategy & REST_MULTIPLE); bool restoring_GPRs_inline = !!(strategy & REST_INLINE_GPRS); @@ -4791,7 +4788,9 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) /* In the ELFv2 ABI we need to restore all call-saved CR fields from *separate* slots if the routine calls __builtin_eh_return, so - that they can be independently restored by the unwinder. */ + that they can be independently restored by the unwinder. Since + it is for CR fields restoring, it should be done for any epilogue + types (not EPILOGUE_TYPE_EH_RETURN specific). */ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return) { int i, cr_off = info->ehcr_offset; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 7e33fb4039a..8d8118197da 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -14147,6 +14147,8 @@ "" { emit_insn (gen_eh_set_lr (Pmode, operands[0])); + emit_jump_insn (gen_eh_return_internal ()); + emit_barrier (); DONE; }) @@ -14163,6 +14165,19 @@ DONE; }) +(define_insn_and_split "eh_return_internal" + [(eh_return)] + "" + "#" + "epilogue_completed" + [(const_int 0)] +{ + if (!TARGET_SCHED_PROLOG) +emit_insn (gen_blockage ()); + rs6000_emit_epilogue (EPILOGUE_TYPE_EH_RETURN); + DONE; +}) + (define_insn "prefetch" [(prefetch (match_operand 0 "indexed_or_indirect_address" "a") (match_operand:SI 1 "const_int_operand" "n") diff --git a/gcc/testsuite/gcc.target/powerpc/pr114846.c b/gcc/testsuite/gcc.target/powerpc/pr114846.c new file mode 100644 index 000..efe2300b73a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr114846.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target builtin_eh_return } */ + +/* Ensure it runs successfully. */ + +__attribute__ ((noipa)) +int f (int *a, long offset, void *handler) +{ + if (*a == 5) +return 5; + __builtin_eh_return (offset, handler); +} + +int main () +{ + int t = 5; + if (f (&t, 0, 0) != 5) +__builtin_abort (); + return 0; +}
[gcc r12-10579] rs6000: Don't clobber return value when eh_return called [PR114846]
https://gcc.gnu.org/g:0fd6ae9b20913ab84d596448e14411eedbd324f9 commit r12-10579-g0fd6ae9b20913ab84d596448e14411eedbd324f9 Author: Kewen Lin Date: Tue May 28 21:13:40 2024 -0500 rs6000: Don't clobber return value when eh_return called [PR114846] As the associated test case in PR114846 shows, currently with eh_return involved some register restoring for EH RETURN DATA in epilogue can clobber the one which holding the return value. Referring to the existing handlings in some other targets, this patch makes eh_return expander call one new define_insn_and_split eh_return_internal which directly calls rs6000_emit_epilogue with epilogue_type EPILOGUE_TYPE_EH_RETURN instead of the previous treating normal return with crtl->calls_eh_return specially. PR target/114846 gcc/ChangeLog: * config/rs6000/rs6000-logue.cc (rs6000_emit_epilogue): As EPILOGUE_TYPE_EH_RETURN would be passed as epilogue_type directly now, adjust the relevant handlings on it. * config/rs6000/rs6000.md (eh_return expander): Append by calling gen_eh_return_internal and emit_barrier. (eh_return_internal): New define_insn_and_split, call function rs6000_emit_epilogue with epilogue type EPILOGUE_TYPE_EH_RETURN. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr114846.c: New test. (cherry picked from commit e5fc5d42d25c86ae48178db04ce64d340a834614) Diff: --- gcc/config/rs6000/rs6000-logue.cc | 7 +++ gcc/config/rs6000/rs6000.md | 15 +++ gcc/testsuite/gcc.target/powerpc/pr114846.c | 20 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index a868ede24fb..33077b72611 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -4283,9 +4283,6 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) rs6000_stack_t *info = rs6000_stack_info (); - if (epilogue_type == EPILOGUE_TYPE_NORMAL && crtl->calls_eh_return) -epilogue_type = EPILOGUE_TYPE_EH_RETURN; - int strategy = info->savres_strategy; bool using_load_multiple = !!(strategy & REST_MULTIPLE); bool restoring_GPRs_inline = !!(strategy & REST_INLINE_GPRS); @@ -4763,7 +4760,9 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) /* In the ELFv2 ABI we need to restore all call-saved CR fields from *separate* slots if the routine calls __builtin_eh_return, so - that they can be independently restored by the unwinder. */ + that they can be independently restored by the unwinder. Since + it is for CR fields restoring, it should be done for any epilogue + types (not EPILOGUE_TYPE_EH_RETURN specific). */ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return) { int i, cr_off = info->ehcr_offset; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 2f69c89c689..c38bebde185 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -14039,6 +14039,8 @@ "" { emit_insn (gen_eh_set_lr (Pmode, operands[0])); + emit_jump_insn (gen_eh_return_internal ()); + emit_barrier (); DONE; }) @@ -14055,6 +14057,19 @@ DONE; }) +(define_insn_and_split "eh_return_internal" + [(eh_return)] + "" + "#" + "epilogue_completed" + [(const_int 0)] +{ + if (!TARGET_SCHED_PROLOG) +emit_insn (gen_blockage ()); + rs6000_emit_epilogue (EPILOGUE_TYPE_EH_RETURN); + DONE; +}) + (define_insn "prefetch" [(prefetch (match_operand 0 "indexed_or_indirect_address" "a") (match_operand:SI 1 "const_int_operand" "n") diff --git a/gcc/testsuite/gcc.target/powerpc/pr114846.c b/gcc/testsuite/gcc.target/powerpc/pr114846.c new file mode 100644 index 000..efe2300b73a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr114846.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target builtin_eh_return } */ + +/* Ensure it runs successfully. */ + +__attribute__ ((noipa)) +int f (int *a, long offset, void *handler) +{ + if (*a == 5) +return 5; + __builtin_eh_return (offset, handler); +} + +int main () +{ + int t = 5; + if (f (&t, 0, 0) != 5) +__builtin_abort (); + return 0; +}
[gcc r11-11535] rs6000: Don't clobber return value when eh_return called [PR114846]
https://gcc.gnu.org/g:549701628b64a7c4ac9bb5f9623e83a8dc1d828c commit r11-11535-g549701628b64a7c4ac9bb5f9623e83a8dc1d828c Author: Kewen Lin Date: Tue May 28 21:13:40 2024 -0500 rs6000: Don't clobber return value when eh_return called [PR114846] As the associated test case in PR114846 shows, currently with eh_return involved some register restoring for EH RETURN DATA in epilogue can clobber the one which holding the return value. Referring to the existing handlings in some other targets, this patch makes eh_return expander call one new define_insn_and_split eh_return_internal which directly calls rs6000_emit_epilogue with epilogue_type EPILOGUE_TYPE_EH_RETURN instead of the previous treating normal return with crtl->calls_eh_return specially. PR target/114846 gcc/ChangeLog: * config/rs6000/rs6000-logue.c (rs6000_emit_epilogue): As EPILOGUE_TYPE_EH_RETURN would be passed as epilogue_type directly now, adjust the relevant handlings on it. * config/rs6000/rs6000.md (eh_return expander): Append by calling gen_eh_return_internal and emit_barrier. (eh_return_internal): New define_insn_and_split, call function rs6000_emit_epilogue with epilogue type EPILOGUE_TYPE_EH_RETURN. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr114846.c: New test. (cherry picked from commit e5fc5d42d25c86ae48178db04ce64d340a834614) Diff: --- gcc/config/rs6000/rs6000-logue.c| 7 +++ gcc/config/rs6000/rs6000.md | 15 +++ gcc/testsuite/gcc.target/powerpc/pr114846.c | 20 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index bdcb37c72f5..f84af5515bb 100644 --- a/gcc/config/rs6000/rs6000-logue.c +++ b/gcc/config/rs6000/rs6000-logue.c @@ -4283,9 +4283,6 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) rs6000_stack_t *info = rs6000_stack_info (); - if (epilogue_type == EPILOGUE_TYPE_NORMAL && crtl->calls_eh_return) -epilogue_type = EPILOGUE_TYPE_EH_RETURN; - int strategy = info->savres_strategy; bool using_load_multiple = !!(strategy & REST_MULTIPLE); bool restoring_GPRs_inline = !!(strategy & REST_INLINE_GPRS); @@ -4763,7 +4760,9 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) /* In the ELFv2 ABI we need to restore all call-saved CR fields from *separate* slots if the routine calls __builtin_eh_return, so - that they can be independently restored by the unwinder. */ + that they can be independently restored by the unwinder. Since + it is for CR fields restoring, it should be done for any epilogue + types (not EPILOGUE_TYPE_EH_RETURN specific). */ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return) { int i, cr_off = info->ehcr_offset; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 3462205b532..59091593780 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -13764,6 +13764,8 @@ "" { emit_insn (gen_eh_set_lr (Pmode, operands[0])); + emit_jump_insn (gen_eh_return_internal ()); + emit_barrier (); DONE; }) @@ -13780,6 +13782,19 @@ DONE; }) +(define_insn_and_split "eh_return_internal" + [(eh_return)] + "" + "#" + "epilogue_completed" + [(const_int 0)] +{ + if (!TARGET_SCHED_PROLOG) +emit_insn (gen_blockage ()); + rs6000_emit_epilogue (EPILOGUE_TYPE_EH_RETURN); + DONE; +}) + (define_insn "prefetch" [(prefetch (match_operand 0 "indexed_or_indirect_address" "a") (match_operand:SI 1 "const_int_operand" "n") diff --git a/gcc/testsuite/gcc.target/powerpc/pr114846.c b/gcc/testsuite/gcc.target/powerpc/pr114846.c new file mode 100644 index 000..efe2300b73a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr114846.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target builtin_eh_return } */ + +/* Ensure it runs successfully. */ + +__attribute__ ((noipa)) +int f (int *a, long offset, void *handler) +{ + if (*a == 5) +return 5; + __builtin_eh_return (offset, handler); +} + +int main () +{ + int t = 5; + if (f (&t, 0, 0) != 5) +__builtin_abort (); + return 0; +}
[gcc r15-1572] [PATCH 04/11] Handle pointers for CodeView
https://gcc.gnu.org/g:35cca2ccd908960d789533ddb93bb1bea5e71305 commit r15-1572-g35cca2ccd908960d789533ddb93bb1bea5e71305 Author: Mark Harmstone Date: Sun Jun 23 21:30:08 2024 -0600 [PATCH 04/11] Handle pointers for CodeView Translates DW_TAG_pointer_type DIEs into LF_POINTER symbols, which get output into the .debug$T section. gcc/ * dwarf2codeview.cc (FIRST_TYPE): Define. (struct codeview_custom_type): New structure. (custom_types, last_custom_type): New variables. (get_type_num): Prototype. (write_lf_pointer, write_custom_types): New functions. (codeview_debug_finish): Call write_custom_types. (add_custom_type, get_type_num_pointer_type): New functions. (get_type_num): Handle DW_TAG_pointer_type DIEs. * dwarf2codeview.h (T_VOID): Define. (CV_POINTER_32, CV_POINTER_64): Likewise. (T_32PVOID, T_64PVOID): Likewise. (CV_PTR_NEAR32, CV_PTR64, LF_POINTER): Likewise. Diff: --- gcc/dwarf2codeview.cc | 179 -- gcc/dwarf2codeview.h | 13 2 files changed, 188 insertions(+), 4 deletions(-) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 5006a176260..51401f2d5bc 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see #define CV_CFL_C 0x00 #define CV_CFL_CXX 0x01 +#define FIRST_TYPE 0x1000 + #define LINE_LABEL "Lcvline" #define END_FUNC_LABEL "Lcvendfunc" #define SYMBOL_START_LABEL "Lcvsymstart" @@ -168,6 +170,22 @@ struct die_hasher : free_ptr_hash } }; +struct codeview_custom_type +{ + struct codeview_custom_type *next; + uint32_t num; + uint16_t kind; + + union + { +struct +{ + uint32_t base_type; + uint32_t attributes; +} lf_pointer; + }; +}; + static unsigned int line_label_num; static unsigned int func_label_num; static unsigned int sym_label_num; @@ -181,6 +199,9 @@ static const char* last_filename; static uint32_t last_file_id; static codeview_symbol *sym, *last_sym; static hash_table *types_htab; +static codeview_custom_type *custom_types, *last_custom_type; + +static uint32_t get_type_num (dw_die_ref type); /* Record new line number against the current function. */ @@ -845,6 +866,71 @@ write_codeview_symbols (void) asm_fprintf (asm_out_file, "%LLcv_syms_end:\n"); } +/* Write an LF_POINTER type. */ + +static void +write_lf_pointer (codeview_custom_type *t) +{ + /* This is lf_pointer in binutils and lfPointer in Microsoft's cvinfo.h: + +struct lf_pointer +{ + uint16_t size; + uint16_t kind; + uint32_t base_type; + uint32_t attributes; +} ATTRIBUTE_PACKED; + */ + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n", + t->num, t->num); + + asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, t->kind); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_pointer.base_type); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_pointer.attributes); + putc ('\n', asm_out_file); + + asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num); +} + +/* Write the .debug$T section, which contains all of our custom type + definitions. */ + +static void +write_custom_types (void) +{ + targetm.asm_out.named_section (".debug$T", SECTION_DEBUG, NULL); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, CV_SIGNATURE_C13); + putc ('\n', asm_out_file); + + while (custom_types) +{ + codeview_custom_type *n = custom_types->next; + + switch (custom_types->kind) + { + case LF_POINTER: + write_lf_pointer (custom_types); + break; + } + + free (custom_types); + custom_types = n; +} +} + /* Finish CodeView debug info emission. */ void @@ -861,6 +947,9 @@ codeview_debug_finish (void) write_line_numbers (); write_codeview_symbols (); + if (custom_types) +write_custom_types (); + if (types_htab) delete types_htab; } @@ -993,10 +1082,88 @@ get_type_num_base_type (dw_die_ref type) } } -/* Process a DIE representing a type definition and return its number. If - it's something we can't handle, return 0. We keep a hash table so that - we're not adding the same type multiple times - though if we do it's not - disastrous, as ld will deduplicate everything for us. */ +/* Add a new codeview_custom_type to our singly-linked custom_types list. */ + +static void +add_custom_type (codeview_custom_type *ct) +{ + uint32_t num; + + if (last_custom
[gcc r15-1573] [PATCH 05/11] Handle const and varible modifiers for CodeView
https://gcc.gnu.org/g:29fec9ee74c3219bce714f2e5b6381a48049e01e commit r15-1573-g29fec9ee74c3219bce714f2e5b6381a48049e01e Author: Mark Harmstone Date: Sun Jun 23 21:39:45 2024 -0600 [PATCH 05/11] Handle const and varible modifiers for CodeView gcc/ * dwarf2codeview.cc (struct codeview_custom_type): Add lf_modifier to union. (write_cv_padding, write_lf_modifier): New functions. (write_custom_types): Call write_lf_modifier. (get_type_num_const_type): New function. (get_type_num_volatile_type): Likewise. (get_type_num): Handle DW_TAG_const_type and DW_TAG_volatile_type DIEs. * dwarf2codeview.h (MOD_const, MOD_volatile): Define. (LF_MODIFIER): Likewise. Diff: --- gcc/dwarf2codeview.cc | 157 ++ gcc/dwarf2codeview.h | 5 ++ 2 files changed, 162 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 51401f2d5bc..05f5f60997e 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -183,6 +183,11 @@ struct codeview_custom_type uint32_t base_type; uint32_t attributes; } lf_pointer; +struct +{ + uint32_t base_type; + uint16_t modifier; +} lf_modifier; }; }; @@ -903,6 +908,76 @@ write_lf_pointer (codeview_custom_type *t) asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num); } +/* All CodeView type definitions have to be aligned to a four-byte boundary, + so write some padding bytes if necessary. These have to be specific values: + f3, f2, f1. */ + +static void +write_cv_padding (size_t padding) +{ + if (padding == 4 || padding == 0) +return; + + if (padding == 3) +{ + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, 0xf3); + putc ('\n', asm_out_file); +} + + if (padding >= 2) +{ + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, 0xf2); + putc ('\n', asm_out_file); +} + + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, 0xf1); + putc ('\n', asm_out_file); +} + +/* Write an LF_MODIFIER type, representing a const and/or volatile modification + of another type. */ + +static void +write_lf_modifier (codeview_custom_type *t) +{ + /* This is lf_modifier in binutils and lfModifier in Microsoft's cvinfo.h: + +struct lf_modifier +{ + uint16_t size; + uint16_t kind; + uint32_t base_type; + uint16_t modifier; + uint16_t padding; +} ATTRIBUTE_PACKED; + */ + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n", + t->num, t->num); + + asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, t->kind); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_modifier.base_type); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_modifier.modifier); + putc ('\n', asm_out_file); + + write_cv_padding (2); + + asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num); +} + /* Write the .debug$T section, which contains all of our custom type definitions. */ @@ -924,6 +999,10 @@ write_custom_types (void) case LF_POINTER: write_lf_pointer (custom_types); break; + + case LF_MODIFIER: + write_lf_modifier (custom_types); + break; } free (custom_types); @@ -1159,6 +1238,76 @@ get_type_num_pointer_type (dw_die_ref type) return ct->num; } +/* Process a DW_TAG_const_type DIE, adding an LF_MODIFIER type and returning + its number. */ + +static uint32_t +get_type_num_const_type (dw_die_ref type) +{ + dw_die_ref base_type; + uint32_t base_type_num; + codeview_custom_type *ct; + bool is_volatile = false; + + base_type = get_AT_ref (type, DW_AT_type); + if (!base_type) +return 0; + + /* Handle case when this is a const volatile type - we only need one + LF_MODIFIER for this. */ + if (dw_get_die_tag (base_type) == DW_TAG_volatile_type) +{ + is_volatile = true; + + base_type = get_AT_ref (base_type, DW_AT_type); + if (!base_type) + return 0; +} + + base_type_num = get_type_num (base_type); + if (base_type_num == 0) +return 0; + + ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type)); + + ct->next = NULL; + ct->kind = LF_MODIFIER; + ct->lf_modifier.base_type = base_type_num; + ct->lf_modifier.modifier = MOD_const; + + if (is_volatile) +ct->lf_modifier.modifier |= MOD_volatile; + + add_custom_type (ct); + + return ct->num; +} + +/* Process a DW_TAG_volatile_type DIE, adding an LF_MODIFIER type and + returning its number. */ + +static uin
[gcc r15-1574] [PATCH 06/11] Handle enums for CodeView
https://gcc.gnu.org/g:d820db38870155d941ffcad5846389e0de059534 commit r15-1574-gd820db38870155d941ffcad5846389e0de059534 Author: Mark Harmstone Date: Sun Jun 23 21:48:22 2024 -0600 [PATCH 06/11] Handle enums for CodeView Translates DW_TAG_enumeration_type DIEs into LF_ENUM symbols. gcc/ * dwarf2codeview.cc (MAX_FIELDLIST_SIZE): Define. (struct codeview_integer): New structure. (struct codeview_subtype): Likewise (struct codeview_custom_type): Add lf_fieldlist and lf_enum to union. (write_cv_integer, cv_integer_len): New functions. (write_lf_fieldlist, write_lf_enum): Likewise. (write_custom_types): Call write_lf_fieldlist and write_lf_enum. (add_enum_forward_def): New function. (get_type_num_enumeration_type): Likewise. (get_type_num): Handle DW_TAG_enumeration_type DIEs. * dwarf2codeview.h (LF_FIELDLIST, LF_INDEX, LF_ENUMERATE): Define. (LF_ENUM, LF_CHAR, LF_SHORT, LF_USHORT, LF_LONG): Likewise. (LF_ULONG, LF_QUADWORD, LF_UQUADWORD): Likewise. (CV_ACCESS_PRIVATE, CV_ACCESS_PROTECTED): Likewise. (CV_ACCESS_PUBLIC, CV_PROP_FWDREF): Likewise. Diff: --- gcc/dwarf2codeview.cc | 524 ++ gcc/dwarf2codeview.h | 17 ++ 2 files changed, 541 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 05f5f60997e..475a53573e9 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -63,6 +63,11 @@ along with GCC; see the file COPYING3. If not see #define SYMBOL_START_LABEL "Lcvsymstart" #define SYMBOL_END_LABEL "Lcvsymend" +/* There's two bytes available for each type's size, but follow MSVC's lead in + capping the LF_FIELDLIST size at fb00 (minus 8 bytes for the LF_INDEX + pointing to the overflow entry). */ +#define MAX_FIELDLIST_SIZE 0xfaf8 + #define HASH_SIZE 16 struct codeview_string @@ -170,6 +175,31 @@ struct die_hasher : free_ptr_hash } }; +struct codeview_integer +{ + bool neg; + uint64_t num; +}; + +struct codeview_subtype +{ + struct codeview_subtype *next; + uint16_t kind; + + union + { +struct +{ + char *name; + struct codeview_integer value; +} lf_enumerate; +struct +{ + uint32_t type_num; +} lf_index; + }; +}; + struct codeview_custom_type { struct codeview_custom_type *next; @@ -188,6 +218,20 @@ struct codeview_custom_type uint32_t base_type; uint16_t modifier; } lf_modifier; +struct +{ + size_t length; + codeview_subtype *subtypes; + codeview_subtype *last_subtype; +} lf_fieldlist; +struct +{ + uint16_t count; + uint16_t properties; + uint32_t underlying_type; + uint32_t fieldlist; + char *name; +} lf_enum; }; }; @@ -978,6 +1022,292 @@ write_lf_modifier (codeview_custom_type *t) asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num); } +/* Write a CodeView extensible integer. If the value is non-negative and + < 0x8000, the value gets written directly as an uint16_t. Otherwise, we + output two bytes for the integer type (LF_CHAR, LF_SHORT, ...), and the + actual value follows. */ + +static size_t +write_cv_integer (codeview_integer *i) +{ + if (i->neg) +{ + if (i->num <= 0x80) + { + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, LF_CHAR); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, -i->num); + putc ('\n', asm_out_file); + + return 3; + } + else if (i->num <= 0x8000) + { + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, LF_SHORT); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, -i->num); + putc ('\n', asm_out_file); + + return 4; + } + else if (i->num <= 0x8000) + { + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, LF_LONG); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, -i->num); + putc ('\n', asm_out_file); + + return 6; + } + else + { + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, LF_QUADWORD); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (8, false), asm_out_file); + fprint_whex (asm_out_file, -i->num); + putc ('\n', asm_out_file); + + return 10; + } +} + else +{ + if (i->num <= 0x7fff) + { + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, i->n
[gcc r15-1575] fwprop: invoke change_is_worthwhile to judge if a replacement is worthwhile
https://gcc.gnu.org/g:ea8061f46a301797e7ba33b52e3b4713fb8e6b48 commit r15-1575-gea8061f46a301797e7ba33b52e3b4713fb8e6b48 Author: Haochen Gui Date: Mon Jun 24 13:12:51 2024 +0800 fwprop: invoke change_is_worthwhile to judge if a replacement is worthwhile gcc/ * fwprop.cc (try_fwprop_subst_pattern): Invoke change_is_worthwhile to judge if a replacement is worthwhile. Remove single_set check and add is_debug_insn check. * recog.cc (swap_change): Invalidate recog_data when the cached INSN is swapped out. * rtl-ssa/changes.cc (rtl_ssa::changes_are_worthwhile): Check if the insn cost of new rtl is unknown and fail the replacement. Diff: --- gcc/fwprop.cc | 37 ++--- gcc/recog.cc | 6 +- gcc/rtl-ssa/changes.cc | 8 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/gcc/fwprop.cc b/gcc/fwprop.cc index de543923b92..bfdc7a1b749 100644 --- a/gcc/fwprop.cc +++ b/gcc/fwprop.cc @@ -453,7 +453,7 @@ try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change, && (prop.changed_mem_p () || contains_mem_rtx_p (src) || use_insn->is_asm () - || !single_set (use_rtl))) + || use_insn->is_debug_insn ())) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "cannot propagate from insn %d into" @@ -471,29 +471,20 @@ try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change, redo_changes (0); } - /* ??? In theory, it should be better to use insn costs rather than - set_src_costs here. That would involve replacing this code with - change_is_worthwhile. */ bool ok = recog (attempt, use_change); - if (ok && !prop.changed_mem_p () && !use_insn->is_asm ()) -if (rtx use_set = single_set (use_rtl)) - { - bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_rtl)); - temporarily_undo_changes (0); - auto old_cost = set_src_cost (SET_SRC (use_set), - GET_MODE (SET_DEST (use_set)), speed); - redo_changes (0); - auto new_cost = set_src_cost (SET_SRC (use_set), - GET_MODE (SET_DEST (use_set)), speed); - if (new_cost > old_cost - || (new_cost == old_cost && !prop.likely_profitable_p ())) - { - if (dump_file) - fprintf (dump_file, "change not profitable" - " (cost %d -> cost %d)\n", old_cost, new_cost); - ok = false; - } - } + if (ok + && !prop.changed_mem_p () + && !use_insn->is_asm () + && !use_insn->is_debug_insn ()) +{ + bool strict_p = !prop.likely_profitable_p (); + if (!change_is_worthwhile (use_change, strict_p)) + { + if (dump_file) + fprintf (dump_file, "change not profitable"); + ok = false; + } +} if (!ok) { diff --git a/gcc/recog.cc b/gcc/recog.cc index a6799e3f5e6..56370e40e01 100644 --- a/gcc/recog.cc +++ b/gcc/recog.cc @@ -614,7 +614,11 @@ swap_change (int num) else std::swap (*changes[num].loc, changes[num].old); if (changes[num].object && !MEM_P (changes[num].object)) -std::swap (INSN_CODE (changes[num].object), changes[num].old_code); +{ + std::swap (INSN_CODE (changes[num].object), changes[num].old_code); + if (recog_data.insn == changes[num].object) + recog_data.insn = nullptr; +} } /* Temporarily undo all the changes numbered NUM and up, with a view diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc index 3101f2dc4fc..bc80d7da829 100644 --- a/gcc/rtl-ssa/changes.cc +++ b/gcc/rtl-ssa/changes.cc @@ -190,6 +190,14 @@ rtl_ssa::changes_are_worthwhile (array_slice changes, && INSN_CODE (change->rtl ()) != NOOP_MOVE_INSN_CODE) { change->new_cost = insn_cost (change->rtl (), for_speed); + /* If the cost is unknown, replacement is not worthwhile. */ + if (!change->new_cost) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, +"Reject replacement due to unknown insn cost.\n"); + return false; + } new_cost += change->new_cost; if (for_speed) weighted_new_cost += (cfg_bb->count.to_sreal_scale (entry_count)
[gcc r15-1576] rs6000: Eliminate unnecessary byte swaps for duplicated constant vector store
https://gcc.gnu.org/g:6274f10318d05311f31147c895f76a01aec37830 commit r15-1576-g6274f10318d05311f31147c895f76a01aec37830 Author: Haochen Gui Date: Mon Jun 24 13:16:12 2024 +0800 rs6000: Eliminate unnecessary byte swaps for duplicated constant vector store gcc/ PR target/113325 * config/rs6000/vsx.md (vsx_stxvd2x4_le_const_): New. gcc/testsuite/ PR target/113325 * gcc.target/powerpc/pr113325.c: New. Diff: --- gcc/config/rs6000/vsx.md| 25 + gcc/testsuite/gcc.target/powerpc/pr113325.c | 9 + 2 files changed, 34 insertions(+) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index 7a9c19ac903..48ba262f7e4 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -3368,6 +3368,31 @@ "stxvd2x %x1,%y0" [(set_attr "type" "vecstore")]) +(define_insn_and_split "vsx_stxvd2x4_le_const_" + [(set (match_operand:VSX_W 0 "memory_operand" "=Z") + (match_operand:VSX_W 1 "immediate_operand" "W"))] + "!BYTES_BIG_ENDIAN + && VECTOR_MEM_VSX_P (mode) + && !TARGET_P9_VECTOR + && const_vec_duplicate_p (operands[1]) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (match_dup 2) + (match_dup 1)) + (set (match_dup 0) + (vec_select:VSX_W + (match_dup 2) + (parallel [(const_int 2) (const_int 3) +(const_int 0) (const_int 1)])))] +{ + /* Here all the constants must be loaded without memory. */ + gcc_assert (easy_altivec_constant (operands[1], mode)); + operands[2] = gen_reg_rtx (mode); +} + [(set_attr "type" "vecstore") + (set_attr "length" "8")]) + (define_insn "*vsx_stxvd2x8_le_V8HI" [(set (match_operand:V8HI 0 "memory_operand" "=Z") (vec_select:V8HI diff --git a/gcc/testsuite/gcc.target/powerpc/pr113325.c b/gcc/testsuite/gcc.target/powerpc/pr113325.c new file mode 100644 index 000..3ca1fcbc9ba --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr113325.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power8 -mvsx" } */ +/* { dg-require-effective-target powerpc_vsx } */ +/* { dg-final { scan-assembler-not {\mxxpermdi\M} } } */ + +void* foo (void* s1) +{ + return __builtin_memset (s1, 0, 32); +}