Re: [RFC] RISC-V: Implment H modifier for printing the next register name

2025-04-26 Thread Jin Ma
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.

2025-04-26 Thread Xin Wang
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.

2025-04-26 Thread ywgrit
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

2025-04-26 Thread Xin Wang
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

2025-04-26 Thread H.J. Lu
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.

2025-04-26 Thread Tamar Christina
> -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

2025-04-26 Thread Gerald Pfeifer


---
 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

2025-04-26 Thread Florian Weimer
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

2025-04-26 Thread Arthur Cohen

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

2025-04-26 Thread Andrew Pinski
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]

2025-04-26 Thread Andrew Pinski
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]

2025-04-26 Thread Andrew Pinski
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

2025-04-26 Thread Jeff Law




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)

2025-04-26 Thread Translation Project Robot
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

2025-04-26 Thread Dimitar Dimitrov
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