Re: [RFC] RISC-V: Implment H modifier for printing the next register name
On Sat, 26 Apr 2025 09:59:45 +0300, Dimitar Dimitrov wrote: > On Fri, Apr 25, 2025 at 01:25:50PM +0800, Jin Ma wrote: > > For RV32 inline assembly, when handling 64-bit integer data, it is > > often necessary to process the lower and upper 32 bits separately. > > Unfortunately, we can only output the current register name > > (lower 32 bits) but not the next register name (upper 32 bits). > > > > To address this, the modifier 'H' has been added to allow users > > to handle the upper 32 bits of the data. While I believe the > > modifier 'N' (representing the next register name) might be more > > suitable for this functionality, 'N' is already in use. > > Therefore, 'H' (representing the high register) was chosen instead. > > > > Does anyone have any comments on this? > > > > gcc/ChangeLog: > > > > * config/riscv/riscv.cc (riscv_print_operand): Add H. > > * doc/extend.texi: Document for H. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.target/riscv/modifier-H.c: New test. > > --- > > gcc/config/riscv/riscv.cc | 12 +++ > > gcc/doc/extend.texi | 1 + > > gcc/testsuite/gcc.target/riscv/modifier-H.c | 22 + > > 3 files changed, 35 insertions(+) > > create mode 100644 gcc/testsuite/gcc.target/riscv/modifier-H.c > > > > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > > index bad59e248d0..4ef96532f35 100644 > > --- a/gcc/config/riscv/riscv.cc > > +++ b/gcc/config/riscv/riscv.cc > > @@ -6879,6 +6879,7 @@ riscv_asm_output_opcode (FILE *asm_out_file, const > > char *p) > > 'T' Print shift-index of inverted single-bit mask OP. > > '~' Print w if TARGET_64BIT is true; otherwise not print anything. > > 'N' Print register encoding as integer (0-31). > > + 'H' Print the name of the high register for OP, which is the next > > register. > > > > Note please keep this list and the list in riscv.md in sync. */ > > > > @@ -7174,6 +7175,17 @@ riscv_print_operand (FILE *file, rtx op, int letter) > > asm_fprintf (file, "%u", (regno - offset)); > > break; > >} > > +case 'H': > > + { > > + if (!REG_P (op)) > > + { > > + output_operand_lossage ("modifier 'H' require register operand"); > > + break; > > + } > > Given the intended usage, does it make sense to limit this modifier only > to regular integer registers? Example: > > if (REGNO (op) > 31 ) > { > output_operand_lossage ("modifier 'H' is for integer registers only"); > break; > } > if (REGNO (op) == 31 ) > { > output_operand_lossage ("modifier 'H' cannot be applied to R31"); > break; > } > > Is it an error to apply H modifier to R0? > > If not, would you consider rejecting the last HW register: > if (REGNO (op) >= FIRST_PSEUDO_REGISTER - 1 ) > { > output_operand_lossage ("modifier 'H' cannot be applied to last HW > register"); > break; > } Thanks. These are excellent review comments, and I will incorporate them into the next version. Does anyone else have additional suggestions? Best regards, Jin
[PATCH v2] gcc: do not apply store motion on loop with no exits.
The temporary variable will not be wrote back to memory as there is no exit of inifinite loop, so we prohibit applying store motion on loops with no exits. Signed-off-by: Xin Wang --- gcc/tree-ssa-loop-im.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc index 225964c6215..de0450f5192 100644 --- a/gcc/tree-ssa-loop-im.cc +++ b/gcc/tree-ssa-loop-im.cc @@ -3355,6 +3355,9 @@ loop_suitable_for_sm (class loop *loop ATTRIBUTE_UNUSED, unsigned i; edge ex; + if (exits.is_empty()) +return false; + FOR_EACH_VEC_ELT (exits, i, ex) if (ex->flags & (EDGE_ABNORMAL | EDGE_EH)) return false; -- 2.25.1
Re: [PATCH v2] gcc: do not apply store motion on loop with no exits.
I encountered one problem with loop-im pass. I compiled the program dhry2reg which belongs to unixbench( https://github.com/kdlucas/byte-unixbench). The gcc used gcc (GCC) 12.3.0 The commands executed as following make ./Run -c -i 1 dhry2reg The results are shown below. Dhrystone 2 using register variables 0.1 lps (10.0 s, 1 samples) System Benchmarks Partial Index BASELINE RESULTINDEX Dhrystone 2 using register variables 116700.0 0.1 0.0 System Benchmarks Index Score (Partial Only) 10.0 Obviously, the "INDEX" is abnormal. I wrote a demo named dhry.c based on the dhry2reg logic. // dhry.c #include #include #include #include #include int run_index; typedef struct record { struct record *next_rec; int i; } record, *pointer; pointer global_pointer, next_global_pointer; void report() { printf("report:%d\n", run_index); exit(0); } int main() { printf("%d\n", run_index); global_pointer = (pointer )malloc(sizeof(struct record)); next_global_pointer = (pointer )malloc(sizeof(struct record)); global_pointer->next_rec = next_global_pointer; signal(SIGALRM, report); /* get the clock running */ alarm(1); char i[4]; // no exit for(run_index=0;;++run_index){ *global_pointer->next_rec = *global_pointer; } } gcc -O3 -fdump-tree-all -fdump-tree-all-graph dhry.c -o dhry ./dhry 0 report:0 gcc -O3 -fdump-tree-all -fdump-tree-all-graph dhry.c -o dhry -fno-tree-loop-im ./dhry 0 report:1367490190 The generated gimple are shown below. dhry.c.140t.laddress: [local count: 10631108]: run_index.1_1 = run_index; printf ("%d\n", run_index.1_1); _2 = malloc (16); global_pointer = _2; _3 = malloc (16); next_global_pointer = _3; MEM[(struct record *)_2].next_rec = _3; signal (14, report); alarm (1); run_index = 0; [local count: 1073741824]: global_pointer.4_4 = global_pointer; _5 = global_pointer.4_4->next_rec; *_5 = *global_pointer.4_4; run_index.6_6 = run_index; _7 = run_index.6_6 + 1; run_index = _7; goto ; [100.00%] dhry.c.142t.lim2: [local count: 10631108]: run_index.1_1 = run_index; printf ("%d\n", run_index.1_1); _2 = malloc (16); global_pointer = _2; _3 = malloc (16); next_global_pointer = _3; MEM[(struct record *)_2].next_rec = _3; signal (14, report); alarm (1); run_index = 0; global_pointer.4_4 = global_pointer; run_index_lsm.13_22 = run_index; [local count: 1073741824]: # run_index_lsm.13_21 = PHI _5 = global_pointer.4_4->next_rec; *_5 = *global_pointer.4_4; run_index.6_6 = run_index_lsm.13_21; _7 = run_index.6_6 + 1; run_index_lsm.13_23 = _7; In loop-im pass, store-motion insert run_index_lsm = run_index before loop and replace all references of run_index with run_index_lsm. And the following code writes run_index_lsm back to run_index. /* Materialize ordered store sequences on exits. */ FOR_EACH_VEC_ELT (exits, i, e) { edge append_cond_position = NULL; edge last_cond_fallthru = NULL; if (i < sms.length ()) { gcc_assert (sms[i].first == e); execute_sm_exit (loop, e, sms[i].second, aux_map, sm_ord, append_cond_position, last_cond_fallthru); sms[i].second.release (); } if (!unord_refs.is_empty ()) execute_sm_exit (loop, e, unord_refs, aux_map, sm_unord, append_cond_position, last_cond_fallthru); /* Commit edge inserts here to preserve the order of stores when an exit exits multiple loops. */ gsi_commit_one_edge_insert (e, NULL); } But run_index_lsm is not wrote back to run_index as there is no exit in this loop. so run_index will be zero after store motion is executed. Is inifinite loop a undefined behavior, so it is permitted if run_index == 0? If not, I think we should not apply store motion on loop with no exit. Xin Wang 于2025年4月27日周日 11:29写道: > The temporary variable will not be wrote back to memory as there > is no exit of inifinite loop, so we prohibit applying store motion > on loops with no exits. > > Signed-off-by: Xin Wang > > --- > gcc/tree-ssa-loop-im.cc | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc > index 225964c6215..de0450f5192 100644 > --- a/gcc/tree-ssa-loop-im.cc > +++ b/gcc/tree-ssa-loop-im.cc > @@ -3355,6 +3355,9 @@ loop_suitable_for_sm (class loop *loop > ATTRIBUTE_UNUSED, >unsigned i; >edge ex; > > + if (exits.is_empty()) > +return false; > + >FOR_EACH_VEC_ELT (exits, i, ex) > if (ex->flags & (EDGE_ABNORMAL | EDGE_EH)) >return false; > -- > 2.25.1 > >
[PATCH] gcc: do not apply store motion on loop with no exits. The temporary variable will not be wrote back to memory as there is no exit of inifinite loop, so we prohibit applying store motion on loo
Signed-off-by: Xin Wang --- gcc/tree-ssa-loop-im.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc index 225964c6215..de0450f5192 100644 --- a/gcc/tree-ssa-loop-im.cc +++ b/gcc/tree-ssa-loop-im.cc @@ -3355,6 +3355,9 @@ loop_suitable_for_sm (class loop *loop ATTRIBUTE_UNUSED, unsigned i; edge ex; + if (exits.is_empty()) +return false; + FOR_EACH_VEC_ELT (exits, i, ex) if (ex->flags & (EDGE_ABNORMAL | EDGE_EH)) return false; -- 2.25.1
[PATCH] i386: Add ix86_expand_unsigned_small_int_cst_argument
When passing 0xff as an unsigned char function argument with the C frontend promotion, expand_normal used to get constant 255> and returned the rtx value using the sign-extended representation: (const_int 255 [0xff]) But after commit a670ebde3995481225ec62b29686ec07a21e5c10 Author: H.J. Lu Date: Thu Nov 21 07:54:35 2024 +0800 Drop targetm.promote_prototypes from C, C++ and Ada frontends expand_normal now gets co nstant 255> and returns (const_int -1 [0x]) which doesn't work with the predicates nor the instruction templates which expect the unsigned expanded value. Extract the unsigned char and short integer constants to return (const_int 255 [0xff]) so that the expanded value is always unsigned, without the C frontend promotion. PR target/117547 * config/i386/i386-expand.cc (ix86_expand_unsigned_small_int_cst_argumen t): New function. (ix86_expand_args_builtin): Call ix86_expand_unsigned_small_int_cst_argument to expand the argument before calling fixup_modeless_constant. (ix86_expand_round_builtin): Likewise. (ix86_expand_special_args_builtin): Likewise. (ix86_expand_builtin): Likewise. -- H.J. From a7d29729de7451f5ef47d85480905fec0670bd7c Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 12 Nov 2024 09:03:31 +0800 Subject: [PATCH] i386: Add ix86_expand_unsigned_small_int_cst_argument When passing 0xff as an unsigned char function argument with the C frontend promotion, expand_normal used to get constant 255> and returned the rtx value using the sign-extended representation: (const_int 255 [0xff]) But after commit a670ebde3995481225ec62b29686ec07a21e5c10 Author: H.J. Lu Date: Thu Nov 21 07:54:35 2024 +0800 Drop targetm.promote_prototypes from C, C++ and Ada frontends expand_normal now gets constant 255> and returns (const_int -1 [0x]) which doesn't work with the predicates nor the instruction templates which expect the unsigned expanded value. Extract the unsigned char and short integer constants to return (const_int 255 [0xff]) so that the expanded value is always unsigned, without the C frontend promotion. PR target/117547 * config/i386/i386-expand.cc (ix86_expand_unsigned_small_int_cst_argument): New function. (ix86_expand_args_builtin): Call ix86_expand_unsigned_small_int_cst_argument to expand the argument before calling fixup_modeless_constant. (ix86_expand_round_builtin): Likewise. (ix86_expand_special_args_builtin): Likewise. (ix86_expand_builtin): Likewise. Signed-off-by: H.J. Lu --- gcc/config/i386/i386-expand.cc | 58 +++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index a3148008089..388e65192e4 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -11250,6 +11250,54 @@ fixup_modeless_constant (rtx x, machine_mode mode) return x; } +/* Expand the outgoing argument ARG to extract unsigned char and short + integer constants suitable for the predicates and the instruction + templates which expect the unsigned expanded value. */ + +static rtx +ix86_expand_unsigned_small_int_cst_argument (tree arg) +{ + /* When passing 0xff as an unsigned char function argument with the + C frontend promotion, expand_normal gets + + constant 255> + + and returns the rtx value using the sign-extended representation: + + (const_int 255 [0xff]) + + Without the C frontend promotion, expand_normal gets + + constant 255> + + and returns + + (const_int -1 [0x]) + + which doesn't work with the predicates nor the instruction templates + which expect the unsigned expanded value. Extract the unsigned char + and short integer constants to return + + (const_int 255 [0xff]) + + so that the expanded value is always unsigned, without the C frontend + promotion. */ + + if (TREE_CODE (arg) == INTEGER_CST) +{ + tree type = TREE_TYPE (arg); + if (INTEGRAL_TYPE_P (type) + && TYPE_UNSIGNED (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + { + HOST_WIDE_INT cst = TREE_INT_CST_LOW (arg); + return GEN_INT (cst); + } +} + + return expand_normal (arg); +} + /* Subroutine of ix86_expand_builtin to take care of insns with variable number of operands. */ @@ -12148,7 +12196,7 @@ ix86_expand_args_builtin (const struct builtin_description *d, for (i = 0; i < nargs; i++) { tree arg = CALL_EXPR_ARG (exp, i); - rtx op = expand_normal (arg); + rtx op = ix86_expand_unsigned_small_int_cst_argument (arg); machine_mode mode = insn_p->operand[i + 1].mode; /* Need to fixup modeless constant before testing predicate. */ op = fixup_modeless_constant (op, mode); @@ -12843,7 +12891,7 @@ ix86_expand_round_builtin (const struct builtin_description *d, for (i = 0; i < nargs; i++) { tree arg = CALL_EXPR_ARG (exp,
RE: [PATCH] aarch64: Optimize SVE extract last to Neon lane extract for 128-bit VLS.
> -Original Message- > From: Richard Sandiford > Sent: Friday, April 25, 2025 4:45 PM > To: Jennifer Schmitz > Cc: gcc-patches@gcc.gnu.org > Subject: Re: [PATCH] aarch64: Optimize SVE extract last to Neon lane extract > for > 128-bit VLS. > > Jennifer Schmitz writes: > > For the test case > > int32_t foo (svint32_t x) > > { > > svbool_t pg = svpfalse (); > > return svlastb_s32 (pg, x); > > } > > compiled with -O3 -mcpu=grace -msve-vector-bits=128, GCC produced: > > foo: > > pfalse p3.b > > lastb w0, p3, z0.s > > ret > > when it could use a Neon lane extract instead: > > foo: > > umovw0, v0.s[3] > > ret > > > > We implemented this optimization by guarding the emission of > > pfalse+lastb in the pattern vec_extract by > > known_gt (BYTES_PER_SVE_VECTOR, 16). Thus, for a last-extract operation > > in 128-bit VLS, the pattern *vec_extract_v128 is used instead. > > > > The patch was bootstrapped and tested on aarch64-linux-gnu, no regression. > > OK for mainline? > > > > Signed-off-by: Jennifer Schmitz > > > > gcc/ > > * config/aarch64/aarch64-sve.md (vec_extract): > > Prevent the emission of pfalse+lastb for 128-bit VLS. > > > > gcc/testsuite/ > > * gcc.target/aarch64/sve/extract_last_128.c: New test. > > OK, thanks. > Hi Both, If I may, how about viewing this transformation differently. How about instead make pfalse + lastb become rev + umov, which is faster on all Arm micro-architectures for both VLS and VLA and then the optimization becomes lowering rev + umov for VL128 into umov[3]? This would speed up this case for everything. It would also be good to have a test that checks that #include int foo (svint32_t a) { return svrev (a)[0]; } Works. At the moment, with -msve-vector-bits=128 GCC transforms this back into lastb, which is a de-optimization. Your current patch does fix it so would be good to test this too. Thanks, Tamar > Richard > > > --- > > gcc/config/aarch64/aarch64-sve.md | 7 ++-- > > .../gcc.target/aarch64/sve/extract_last_128.c | 33 +++ > > 2 files changed, 37 insertions(+), 3 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/extract_last_128.c > > > > diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64- > sve.md > > index 3dbd65986ec..824bd877e47 100644 > > --- a/gcc/config/aarch64/aarch64-sve.md > > +++ b/gcc/config/aarch64/aarch64-sve.md > > @@ -2969,10 +2969,11 @@ > > { > > poly_int64 val; > > if (poly_int_rtx_p (operands[2], &val) > > - && known_eq (val, GET_MODE_NUNITS (mode) - 1)) > > + && known_eq (val, GET_MODE_NUNITS (mode) - 1) > > + && known_gt (BYTES_PER_SVE_VECTOR, 16)) > > { > > - /* The last element can be extracted with a LASTB and a false > > - predicate. */ > > + /* Extract the last element with a LASTB and a false predicate. > > + Exclude 128-bit VLS to use *vec_extract_v128. */ > > rtx sel = aarch64_pfalse_reg (mode); > > emit_insn (gen_extract_last_ (operands[0], sel, operands[1])); > > DONE; > > diff --git a/gcc/testsuite/gcc.target/aarch64/sve/extract_last_128.c > b/gcc/testsuite/gcc.target/aarch64/sve/extract_last_128.c > > new file mode 100644 > > index 000..71d3561ec60 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/aarch64/sve/extract_last_128.c > > @@ -0,0 +1,33 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O3 -msve-vector-bits=128" } */ > > + > > +#include > > + > > +#define TEST(TYPE, TY) \ > > + TYPE exract_last_##TY (sv##TYPE x) \ > > + {\ > > +svbool_t pg = svpfalse (); \ > > +return svlastb_##TY (pg, x); \ > > + } > > + > > +TEST(bfloat16_t, bf16) > > +TEST(float16_t, f16) > > +TEST(float32_t, f32) > > +TEST(float64_t, f64) > > +TEST(int8_t, s8) > > +TEST(int16_t, s16) > > +TEST(int32_t, s32) > > +TEST(int64_t, s64) > > +TEST(uint8_t, u8) > > +TEST(uint16_t, u16) > > +TEST(uint32_t, u32) > > +TEST(uint64_t, u64) > > + > > +/* { dg-final { scan-assembler-times {\tdup\th0, v0\.h\[7\]} 2 } } */ > > +/* { dg-final { scan-assembler-times {\tdup\ts0, v0\.s\[3\]} 1 } } */ > > +/* { dg-final { scan-assembler-times {\tdup\td0, v0\.d\[1\]} 1 } } */ > > +/* { dg-final { scan-assembler-times {\tumov\tw0, v0\.h\[7\]} 2 } } */ > > +/* { dg-final { scan-assembler-times {\tumov\tw0, v0\.b\[15\]} 2 } } */ > > +/* { dg-final { scan-assembler-times {\tumov\tw0, v0\.s\[3\]} 2 } } */ > > +/* { dg-final { scan-assembler-times {\tumov\tx0, v0\.d\[1\]} 2 } } */ > > +/* { dg-final { scan-assembler-not "lastb" } } */ > > \ No newline at end of file
[pushed] wwwdocs: gcc-15: Fix markup
--- htdocs/gcc-15/changes.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/gcc-15/changes.html b/htdocs/gcc-15/changes.html index 1b7d0e1b..6659574f 100644 --- a/htdocs/gcc-15/changes.html +++ b/htdocs/gcc-15/changes.html @@ -388,7 +388,7 @@ asm (".text; %cc0: mov %cc2, %%r0; .previous;" text message of the diagnostic, and the quoted source. For example, in: + alt="screenshot of a C type error from GCC 15 showing color usage"> the left-hand type is shown in green and the right-hand type in dark blue. @@ -1344,7 +1344,7 @@ asm (".text; %cc0: mov %cc2, %%r0; .previous;" where "text" has a string value such as: -"22 | /* end admins only {{ :*/\n" +"22 | /* end admins only {{ :*/\n" " | ^\n" " || ||\n" " || |end of bidirectional context\n" -- 2.49.0
[PATCH] c: Suppress -Wdeprecated-non-prototype warnings for builtins
Builtins defined with BT_FN_INT_VAR etc. show as functions without a prototype and trigger the warning. gcc/c/ PR c/119950 * c-typeck.cc (convert_arguments): Check for built-in function declaration before warning. gcc/testsuite/ * gcc.dg/Wdeprecated-non-prototype-5.c: New test. --- gcc/c/c-typeck.cc | 3 ++- gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-5.c | 14 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 55d896e02df..f8d1f711513 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -4342,7 +4342,8 @@ convert_arguments (location_t loc, vec arg_loc, tree fntype, builtin_typetail = NULL_TREE; } - if (!typetail && parmnum == 0 && !TYPE_NO_NAMED_ARGS_STDARG_P (fntype)) + if (!typetail && parmnum == 0 && !TYPE_NO_NAMED_ARGS_STDARG_P (fntype) + && !fndecl_built_in_p (fundecl)) { auto_diagnostic_group d; bool warned; diff --git a/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-5.c b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-5.c new file mode 100644 index 000..b231a74cebe --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-5.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-Wdeprecated-non-prototype" } */ + +static inline +int f (int x) +{ + return __builtin_constant_p (x); +} + +static inline +int g (double x) +{ + return __builtin_isfinite (x); +} base-commit: 0035613389a939043d654aea7a76faae95f69422
Re: [wwwdocs] gcc-15: Add changes for Rust frontend
Patch has been committed and pushed upstream. Best, Arthur On 4/25/25 4:30 PM, arthur.co...@embecosm.com wrote: From: Arthur Cohen Content was validated using the Nu HTML checker per the contributing doc. --- htdocs/gcc-15/changes.html | 57 ++ 1 file changed, 57 insertions(+) diff --git a/htdocs/gcc-15/changes.html b/htdocs/gcc-15/changes.html index 3e3c6655..10b1ce58 100644 --- a/htdocs/gcc-15/changes.html +++ b/htdocs/gcc-15/changes.html @@ -702,6 +702,63 @@ asm (".text; %cc0: mov %cc2, %%r0; .previous;" +Rust + + + Basic inline assembly support has been added to the frontend, which enables us to compile +the architecture specific functions of core 1.49. + + + Support for for-loops has been added. + + + Fixes to our automatic dereferencing algorithm for Deref and +DerefMut. This makes gccrs more correct and allow to handle +complicated cases where the type-checker would previously fail. + + + Fixes to our indexing and iterator traits handling, which was required for +for-loops to be properly implemented. + + + Our parser is now fully implemented and fully capable of parsing the entirety of +core, alloc and std. It was still lacking in some +areas, especially around unstable features like specialization. + + + Support for the question-mark operator has been added. This enables gccrs to +handle all the error handling code and machinery often used in real world Rust programs, as +well as in core. + + + Fixes to our macro expansion pass which now correctly expands all of core 1.49. +This also includes fixes to our format_args!() handling code, which received +numerous improvements. + + + Support for let-else has been added. While this is not used in core +1.49, it is used in the Rust-for-Linux project, our next major objective for +gccrs. + + + Support for the unstable specialization feature has been added. This is +required for compiling core 1.49 correctly, in which specialization is used to +improve the runtime performance of Rust binaries. + + + Support for more lang-items has been added + + + Lowered minimum required Rust version to 1.49. This allows more systems to compile the Rust +frontend, and also brings us closer to gccrs compiling its own dependencies down +the line. + + + Rewrite of our name resolution algorithm to properly handle the complex import/export +structure used in core 1.49 + + + New Targets and Target Specific Improvements -- Arthur Cohen Toolchain Engineer Embecosm GmbH Geschäftsführer: Jeremy Bennett Niederlassung: Nürnberg Handelsregister: HR-B 36368 www.embecosm.de Fürther Str. 27 90429 Nürnberg Tel.: 091 - 128 707 040 Fax: 091 - 128 707 077 OpenPGP_0x1B3465B044AD9C65.asc Description: OpenPGP public key OpenPGP_signature.asc Description: OpenPGP digital signature
[PATCH 1/2] gimplefe: Simplify handling of identifier based binary operations
While looking into adding __ROTATE_LEFT and __ROTATE_RIGHT, I noticed this code is just a bunch of if statments repeated. Instead we could just use a simple lookup array to do the same thinga and it would be easier to add to the array instead of duplicating the if sequence again. Bootstrapped and tested on x86_64-linux-gnu. gcc/c/ChangeLog: * gimple-parser.cc (gimple_binary_identifier_code): New variable. (c_parser_gimple_binary_expression): Use gimple_binary_identifier_code instead of doing if statements on the strings. Signed-off-by: Andrew Pinski --- gcc/c/gimple-parser.cc | 107 +++-- 1 file changed, 29 insertions(+), 78 deletions(-) diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc index 90b9beb1e9f..34850d7c359 100644 --- a/gcc/c/gimple-parser.cc +++ b/gcc/c/gimple-parser.cc @@ -963,6 +963,27 @@ c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq) return; } +/* A mapping between an identifier to a tree code for binary operations. */ +static const std::pair gimple_binary_identifier_code[] = + { +{"__MULT_HIGHPART", MULT_HIGHPART_EXPR}, +{"__UNLT", UNLT_EXPR}, +{"__UNLE", UNLE_EXPR}, +{"__UNGT", UNGT_EXPR}, +{"__UNGE", UNGE_EXPR}, +{"__UNEQ", UNEQ_EXPR}, +{"__UNORDERED", UNORDERED_EXPR}, +{"__ORDERED", ORDERED_EXPR}, +{"__LTGT", LTGT_EXPR}, +{"__FLOOR_DIV", FLOOR_DIV_EXPR}, +{"__ROUND_DIV", ROUND_DIV_EXPR}, +{"__EXACT_DIV", EXACT_DIV_EXPR}, +{"__CEIL_DIV", CEIL_DIV_EXPR}, +{"__FLOOR_MOD", FLOOR_MOD_EXPR}, +{"__ROUND_MOD", ROUND_MOD_EXPR}, +{"__CEIL_MOD", CEIL_MOD_EXPR}, + }; + /* Parse gimple binary expr. gimple-binary-expression: @@ -1061,86 +1082,16 @@ c_parser_gimple_binary_expression (gimple_parser &parser, tree ret_type) case CPP_NAME: { tree id = c_parser_peek_token (parser)->value; - if (strcmp (IDENTIFIER_POINTER (id), "__MULT_HIGHPART") == 0) - { - code = MULT_HIGHPART_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNLT") == 0) - { - code = UNLT_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNLE") == 0) - { - code = UNLE_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNGT") == 0) - { - code = UNGT_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNGE") == 0) - { - code = UNGE_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNEQ") == 0) - { - code = UNEQ_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__UNORDERED") == 0) - { - code = UNORDERED_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__ORDERED") == 0) - { - code = ORDERED_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__LTGT") == 0) + for (auto &p : gimple_binary_identifier_code) { - code = LTGT_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__FLOOR_DIV") == 0) - { - code = FLOOR_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__ROUND_DIV") == 0) - { - code = ROUND_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__EXACT_DIV") == 0) - { - code = EXACT_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__CEIL_DIV") == 0) - { - code = CEIL_DIV_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__FLOOR_MOD") == 0) - { - code = FLOOR_MOD_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__ROUND_MOD") == 0) - { - code = ROUND_MOD_EXPR; - break; - } - else if (strcmp (IDENTIFIER_POINTER (id), "__CEIL_MOD") == 0) - { - code = CEIL_MOD_EXPR; - break; + if (strcmp (IDENTIFIER_POINTER (id), p.first) == 0) + { + code = p.second; + break; + } } + if (code != ERROR_MARK) + break; } /* Fallthru. */ default: -- 2.43.0
[PATCH 2/2] gimplefe: Round trip of rotates [PR119432]
This adds support for rotate left/right to the GIMPLE front-end via __ROTATE_LEFT/__ROTATE_RIGHT oeprators. PR c/119432 gcc/c/ChangeLog: * gimple-parser.cc (gimple_binary_identifier_code): Add __ROTATE_LEFT and __ROTATE_RIGHT. gcc/ChangeLog: * tree-pretty-print.cc (op_symbol_code): For LROTATE_EXPR, output __ROTATE_LEFT for gimple. For RROTATE_EXPR output __ROTATE_RIGHT for gimple. gcc/testsuite/ChangeLog: * gcc.dg/gimplefe-57.c: New test. Signed-off-by: Andrew Pinski --- gcc/c/gimple-parser.cc | 2 ++ gcc/testsuite/gcc.dg/gimplefe-57.c | 11 +++ gcc/tree-pretty-print.cc | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/gimplefe-57.c diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc index 34850d7c359..5fd1db87453 100644 --- a/gcc/c/gimple-parser.cc +++ b/gcc/c/gimple-parser.cc @@ -982,6 +982,8 @@ static const std::pair gimple_binary_identifier_code[] {"__FLOOR_MOD", FLOOR_MOD_EXPR}, {"__ROUND_MOD", ROUND_MOD_EXPR}, {"__CEIL_MOD", CEIL_MOD_EXPR}, +{"__ROTATE_LEFT", LROTATE_EXPR}, +{"__ROTATE_RIGHT", RROTATE_EXPR}, }; /* Parse gimple binary expr. diff --git a/gcc/testsuite/gcc.dg/gimplefe-57.c b/gcc/testsuite/gcc.dg/gimplefe-57.c new file mode 100644 index 000..d3eca56119d --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-57.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +int __GIMPLE +foo (int a, int b) +{ + int tem; + tem = a __ROTATE_LEFT b; + tem = tem __ROTATE_RIGHT b; + return tem; +} diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index c1a21e77bd2..359359d98c2 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -4795,10 +4795,10 @@ op_symbol_code (enum tree_code code, dump_flags_t flags) return ">>"; case LROTATE_EXPR: - return "r<<"; + return (flags & TDF_GIMPLE) ? "__ROTATE_LEFT" : "r<<"; case RROTATE_EXPR: - return "r>>"; + return (flags & TDF_GIMPLE) ? "__ROTATE_RIGHT" : "r>>"; case WIDEN_LSHIFT_EXPR: return "w<<"; -- 2.43.0
[PATCH] cfgexpand: Change __builtin_unreachable to __builtin_trap if only thing in function [PR109267]
When we have an empty function, things can go wrong with cfi_startproc/cfi_endproc and a few other things like exceptions. So if the only thing the function does is a call to __builtin_unreachable, let's expand that to a __builtin_trap instead. For most targets that is one instruction wide so it won't hurt things that much and we get correct behavior for exceptions and some linkers will be better for it. Bootstrapped and tested on x86_64-linux-gnu. PR middle-end/109267 gcc/ChangeLog: * cfgexpand.cc (expand_gimple_basic_block): If the first non debug statement in the first (and only) basic block is a call to __builtin_unreachable change it to a call to __builtin_trap. gcc/testsuite/ChangeLog: * gcc.dg/pr109267-1.c: New test. * gcc.dg/pr109267-2.c: New test. Signed-off-by: Andrew Pinski --- gcc/cfgexpand.cc | 8 gcc/testsuite/gcc.dg/pr109267-1.c | 14 ++ gcc/testsuite/gcc.dg/pr109267-2.c | 13 + 3 files changed, 35 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/pr109267-1.c create mode 100644 gcc/testsuite/gcc.dg/pr109267-2.c diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc index e84f12a5e93..e14df760b7a 100644 --- a/gcc/cfgexpand.cc +++ b/gcc/cfgexpand.cc @@ -6206,6 +6206,14 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) basic_block new_bb; stmt = gsi_stmt (gsi); + + /* If we are expanding the first (and only) bb and the only non debug +statement is __builtin_unreachable call, then replace it with a trap +so the function is at least one instruction in size. */ + if (!nondebug_stmt_seen && bb->index == NUM_FIXED_BLOCKS + && gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE)) + gimple_call_set_fndecl(stmt, builtin_decl_implicit (BUILT_IN_TRAP)); + if (!is_gimple_debug (stmt)) nondebug_stmt_seen = true; diff --git a/gcc/testsuite/gcc.dg/pr109267-1.c b/gcc/testsuite/gcc.dg/pr109267-1.c new file mode 100644 index 000..4f1da8b41e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109267-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand-details" } */ + +/* PR middle-end/109267 */ + +int f(void) +{ + __builtin_unreachable(); +} + +/* This unreachable should expand as trap. */ + +/* { dg-final { scan-rtl-dump-times "__builtin_trap " 1 "expand"} } */ +/* { dg-final { scan-rtl-dump-times "__builtin_unreachable " 1 "expand"} } */ diff --git a/gcc/testsuite/gcc.dg/pr109267-2.c b/gcc/testsuite/gcc.dg/pr109267-2.c new file mode 100644 index 000..e6da4860998 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109267-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand-details" } */ + +/* PR middle-end/109267 */ +void g(void); +int f(int *t) +{ + g(); + __builtin_unreachable(); +} + +/* This should be expanded to unreachable so it should show up twice. */ +/* { dg-final { scan-rtl-dump-times "__builtin_unreachable " 2 "expand"} } */ -- 2.43.0
Re: [RFC] RISC-V: Implment H modifier for printing the next register name
On 4/26/25 2:46 AM, Jin Ma wrote: On Sat, 26 Apr 2025 09:59:45 +0300, Dimitar Dimitrov wrote: On Fri, Apr 25, 2025 at 01:25:50PM +0800, Jin Ma wrote: For RV32 inline assembly, when handling 64-bit integer data, it is often necessary to process the lower and upper 32 bits separately. Unfortunately, we can only output the current register name (lower 32 bits) but not the next register name (upper 32 bits). To address this, the modifier 'H' has been added to allow users to handle the upper 32 bits of the data. While I believe the modifier 'N' (representing the next register name) might be more suitable for this functionality, 'N' is already in use. Therefore, 'H' (representing the high register) was chosen instead. Does anyone have any comments on this? gcc/ChangeLog: * config/riscv/riscv.cc (riscv_print_operand): Add H. * doc/extend.texi: Document for H. gcc/testsuite/ChangeLog: * gcc.target/riscv/modifier-H.c: New test. --- gcc/config/riscv/riscv.cc | 12 +++ gcc/doc/extend.texi | 1 + gcc/testsuite/gcc.target/riscv/modifier-H.c | 22 + 3 files changed, 35 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/modifier-H.c diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index bad59e248d0..4ef96532f35 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -6879,6 +6879,7 @@ riscv_asm_output_opcode (FILE *asm_out_file, const char *p) 'T'Print shift-index of inverted single-bit mask OP. '~'Print w if TARGET_64BIT is true; otherwise not print anything. 'N' Print register encoding as integer (0-31). + 'H' Print the name of the high register for OP, which is the next register. Note please keep this list and the list in riscv.md in sync. */ @@ -7174,6 +7175,17 @@ riscv_print_operand (FILE *file, rtx op, int letter) asm_fprintf (file, "%u", (regno - offset)); break; } +case 'H': + { + if (!REG_P (op)) + { + output_operand_lossage ("modifier 'H' require register operand"); + break; + } Given the intended usage, does it make sense to limit this modifier only to regular integer registers? Example: if (REGNO (op) > 31 ) { output_operand_lossage ("modifier 'H' is for integer registers only"); break; } if (REGNO (op) == 31 ) { output_operand_lossage ("modifier 'H' cannot be applied to R31"); break; } Is it an error to apply H modifier to R0? If not, would you consider rejecting the last HW register: if (REGNO (op) >= FIRST_PSEUDO_REGISTER - 1 ) { output_operand_lossage ("modifier 'H' cannot be applied to last HW register"); break; } Thanks. These are excellent review comments, and I will incorporate them into the next version. Does anyone else have additional suggestions? I think with Dimitar's suggestions this patch is OK for the trunk. Thanks! jeff
New Croatian PO file for 'gcc' (version 15.1.0)
Hello, gentle maintainer. This is a message from the Translation Project robot. A revised PO file for textual domain 'gcc' has been submitted by the Croatian team of translators. The file is available at: https://translationproject.org/latest/gcc/hr.po (This file, 'gcc-15.1.0.hr.po', has just now been sent to you in a separate email.) All other PO files for your package are available in: https://translationproject.org/latest/gcc/ Please consider including all of these in your next release, whether official or a pretest. Whenever you have a new distribution with a new version number ready, containing a newer POT file, please send the URL of that distribution tarball to the address below. The tarball may be just a pretest or a snapshot, it does not even have to compile. It is just used by the translators when they need some extra translation context. The following HTML page has been updated: https://translationproject.org/domain/gcc.html If any question arises, please contact the translation coordinator. Thank you for all your work, The Translation Project robot, in the name of your translation coordinator.
Re: [RFC] RISC-V: Implment H modifier for printing the next register name
On Fri, Apr 25, 2025 at 01:25:50PM +0800, Jin Ma wrote: > For RV32 inline assembly, when handling 64-bit integer data, it is > often necessary to process the lower and upper 32 bits separately. > Unfortunately, we can only output the current register name > (lower 32 bits) but not the next register name (upper 32 bits). > > To address this, the modifier 'H' has been added to allow users > to handle the upper 32 bits of the data. While I believe the > modifier 'N' (representing the next register name) might be more > suitable for this functionality, 'N' is already in use. > Therefore, 'H' (representing the high register) was chosen instead. > > Does anyone have any comments on this? > > gcc/ChangeLog: > > * config/riscv/riscv.cc (riscv_print_operand): Add H. > * doc/extend.texi: Document for H. > > gcc/testsuite/ChangeLog: > > * gcc.target/riscv/modifier-H.c: New test. > --- > gcc/config/riscv/riscv.cc | 12 +++ > gcc/doc/extend.texi | 1 + > gcc/testsuite/gcc.target/riscv/modifier-H.c | 22 + > 3 files changed, 35 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/riscv/modifier-H.c > > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > index bad59e248d0..4ef96532f35 100644 > --- a/gcc/config/riscv/riscv.cc > +++ b/gcc/config/riscv/riscv.cc > @@ -6879,6 +6879,7 @@ riscv_asm_output_opcode (FILE *asm_out_file, const char > *p) > 'T' Print shift-index of inverted single-bit mask OP. > '~' Print w if TARGET_64BIT is true; otherwise not print anything. > 'N' Print register encoding as integer (0-31). > + 'H' Print the name of the high register for OP, which is the next > register. > > Note please keep this list and the list in riscv.md in sync. */ > > @@ -7174,6 +7175,17 @@ riscv_print_operand (FILE *file, rtx op, int letter) > asm_fprintf (file, "%u", (regno - offset)); > break; >} > +case 'H': > + { > + if (!REG_P (op)) > + { > + output_operand_lossage ("modifier 'H' require register operand"); > + break; > + } Given the intended usage, does it make sense to limit this modifier only to regular integer registers? Example: if (REGNO (op) > 31 ) { output_operand_lossage ("modifier 'H' is for integer registers only"); break; } if (REGNO (op) == 31 ) { output_operand_lossage ("modifier 'H' cannot be applied to R31"); break; } Is it an error to apply H modifier to R0? If not, would you consider rejecting the last HW register: if (REGNO (op) >= FIRST_PSEUDO_REGISTER - 1 ) { output_operand_lossage ("modifier 'H' cannot be applied to last HW register"); break; } Regards, Dimitar