public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/1] RISC-V: Make "prefetch.i" built-in usable
@ 2023-08-10  3:10 Tsukasa OI
  2023-08-10  3:10 ` [PATCH 1/1] " Tsukasa OI
  0 siblings, 1 reply; 5+ messages in thread
From: Tsukasa OI @ 2023-08-10  3:10 UTC (permalink / raw)
  To: Tsukasa OI, Kito Cheng, Palmer Dabbelt, Andrew Waterman, Jim Wilson
  Cc: gcc-patches

Hello,

I found that a built-in function "__builtin_riscv_zicbop_cbo_prefetchi" is
terribly broken so that this is practically unusable.  It emits the
"prefetch.i" machine instruction HINT but with no usable arguments.

Contents of a.c:

> void function_to_be_called(void);
> 
> void sample(void)
> {
>     __builtin_riscv_zicbop_cbo_prefetchi(&function_to_be_called);
>     function_to_be_called();
> }


Compiling with the 'Zicbop' extension fails.

> $ riscv64-unknown-elf-gcc -O2 -march=rv64i_zicbop -mabi=lp64 -c a.c
> a.c: In function 'sample':
> a.c:5:42: warning: passing argument 1 of '__builtin_riscv_zicbop_cbo_prefetchi' makes integer from pointer without a cast [-Wint-conversion]
>     5 |     __builtin_riscv_zicbop_cbo_prefetchi(&function_to_be_called);
>       |                                          ^~~~~~~~~~~~~~~~~~~~~~
>       |                                          |
>       |                                          void (*)(void)
> a.c:5:42: note: expected 'long int' but argument is of type 'void (*)(void)'
> a.c:5:5: error: invalid argument to built-in function
>     5 |     __builtin_riscv_zicbop_cbo_prefetchi(&function_to_be_called);
>       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

seems the prototype of this built-in function is...

> int  __builtin_riscv_zicbop_cbo_prefetchi(int);  // RV32
> long __builtin_riscv_zicbop_cbo_prefetchi(long); // RV64

I started to have a bad feeling about this.




Looking at the test case, following code compiles (sort of).

> void sample(void)
> {
>     __builtin_riscv_zicbop_cbo_prefetchi(1); /* integer constant: 0-4 (inclusive) */
> }

WHAT IS THIS PREFETCHING!?

The answer was obvious (tested with GCC 13.2.0).

> $ riscv64-unknown-elf-gcc -O2 -march=rv64i_zicbop -mabi=lp64 -S a.c
> $ cat a.s
>         .file   "a.c"
>         .option nopic
>         .attribute arch, "rv64i2p1_zicbop1p0"
>         .attribute unaligned_access, 0
>         .attribute stack_align, 16
>         .text
>         .align  2
>         .globl  sample
>         .type   sample, @function
> sample:
>         li      a5,0
>         prefetch.i      0(a5)
>         ret
>         .size   sample, .-sample
>         .ident  "GCC: (gc891d8dc23e1) 13.2.0"

... none (NULL).  Even the prefetching constant (1) is ignored.




It makes no sense whatsoever.  This patch set is definitely compatibility-
breaking but necessary to make "prefetch.i" work.

This patch set makes following built-in function.

> void  __builtin_riscv_zicbop_prefetch_i(void*);

Did you notice that I renamed the function?  There are three reasons:

1.  We needed to break the compatibility anyway.
2.  To avoid functionality problems.
    Co-existing functional and non-functional
    __builtin_riscv_zicbop_cbo_prefetchi built-in felt like a nightmare.
3.  Although this is also a cache block operation, the instruction
    "prefetch.i" does not have the name "cbo" in it
    (unlike "__builtin_riscv_zicbom_cbo_clean" corresponding "cbo.clean").


Let's make a working sample (a.c):

> void function_to_be_called(void);
> 
> void sample(void)
> {
>     __builtin_riscv_zicbop_prefetch_i(&function_to_be_called);
>     function_to_be_called();
> }

And take look at the output assembly and its relocations.

> $ riscv64-unknown-elf-gcc -O2 -march=rv64i_zicbop -mabi=lp64 -S a.c
> $ cat a.s
>         .file   "a.c"
>         .option nopic
>         .attribute arch, "rv64i2p1_zicbop1p0"
>         .attribute unaligned_access, 0
>         .attribute stack_align, 16
>         .text
>         .align  2
>         .globl  sample
>         .type   sample, @function
> sample:
>         lui     a5,%hi(function_to_be_called)
>         addi    a5,a5,%lo(function_to_be_called)
>         prefetch.i      0(a5)
>         tail    function_to_be_called
>         .size   sample, .-sample
>         .ident  "GCC: (GNU) 14.0.0 20230810 (experimental)"



I hope this issue is fixed soon.

Sincerely,
Tsukasa




Tsukasa OI (1):
  RISC-V: Make "prefetch.i" built-in usable

 gcc/config/riscv/riscv-cmo.def                |  4 ++--
 gcc/config/riscv/riscv.md                     |  5 ++---
 gcc/doc/extend.texi                           |  7 +++++++
 gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c |  8 +++++---
 gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c | 10 ++++++----
 5 files changed, 22 insertions(+), 12 deletions(-)


base-commit: 9b099a83b45b8fcdfc07d518e05d36ea741b2227
-- 
2.41.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/1] RISC-V: Make "prefetch.i" built-in usable
  2023-08-10  3:10 [PATCH 0/1] RISC-V: Make "prefetch.i" built-in usable Tsukasa OI
@ 2023-08-10  3:10 ` Tsukasa OI
  2023-08-28 21:20   ` Jeff Law
  0 siblings, 1 reply; 5+ messages in thread
From: Tsukasa OI @ 2023-08-10  3:10 UTC (permalink / raw)
  To: Tsukasa OI, Kito Cheng, Palmer Dabbelt, Andrew Waterman, Jim Wilson
  Cc: gcc-patches

From: Tsukasa OI <research_trasio@irq.a4lg.com>

The "__builtin_riscv_zicbop_cbo_prefetchi" built-in function was terribly
broken so that practically unusable.  It emitted "prefetch.i" but with no
meaningful arguments.

Though incompatible, this commit completely changes the function prototype
of this built-in and makes it usable.  To minimize the functionality issues,
it renames the built-in to "__builtin_riscv_zicbop_prefetch_i".

gcc/ChangeLog:

	* config/riscv/riscv-cmo.def: Fix function prototype.
	* config/riscv/riscv.md (riscv_prefetchi_<mode>): Fix instruction
	prototype.  Remove possible prefectch type argument
	* doc/extend.texi: Document __builtin_riscv_zicbop_prefetch_i.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/cmo-zicbop-1.c: Reflect new built-in prototype.
	* gcc.target/riscv/cmo-zicbop-2.c: Likewise.
---
 gcc/config/riscv/riscv-cmo.def                |  4 ++--
 gcc/config/riscv/riscv.md                     |  5 ++---
 gcc/doc/extend.texi                           |  7 +++++++
 gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c |  8 +++++---
 gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c | 10 ++++++----
 5 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/gcc/config/riscv/riscv-cmo.def b/gcc/config/riscv/riscv-cmo.def
index b92044dc6ff9..2286c8a25544 100644
--- a/gcc/config/riscv/riscv-cmo.def
+++ b/gcc/config/riscv/riscv-cmo.def
@@ -13,8 +13,8 @@ RISCV_BUILTIN (zero_si, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV
 RISCV_BUILTIN (zero_di, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV_VOID_FTYPE_VOID_PTR, zero64),
 
 // zicbop
-RISCV_BUILTIN (prefetchi_si, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI, prefetchi32),
-RISCV_BUILTIN (prefetchi_di, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_DI, prefetchi64),
+RISCV_BUILTIN (prefetchi_si, "zicbop_prefetch_i", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV_VOID_FTYPE_VOID_PTR, prefetchi32),
+RISCV_BUILTIN (prefetchi_di, "zicbop_prefetch_i", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV_VOID_FTYPE_VOID_PTR, prefetchi64),
 
 // zbkc or zbc
 RISCV_BUILTIN (clmul_si, "clmul", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_SI_SI, clmul_zbkc32_or_zbc32),
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 688fd697255b..5658c7b7e113 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3273,9 +3273,8 @@
 })
 
 (define_insn "riscv_prefetchi_<mode>"
-  [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
-              (match_operand:X 1 "imm5_operand" "i")]
-              UNSPECV_PREI)]
+  [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
+    UNSPECV_PREI)]
   "TARGET_ZICBOP"
   "prefetch.i\t%a0"
 )
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 89c5b4ea2b20..0eb98fc89e3f 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -21575,6 +21575,13 @@ Xgnuzihintpausestate extension, which redefines the @code{pause} instruction to
 change architectural state.
 @enddefbuiltin
 
+@defbuiltin{void __builtin_riscv_zicbop_prefetch_i (void *@var{addr})}
+Generates the @code{prefetch.i} machine instruction to instruct the hardware
+that a cache block containing @var{addr} is likely to be accessed by an
+instruction fetch in the near future.
+Available if the Zicbop extension is enabled.
+@enddefbuiltin
+
 @node RISC-V Vector Intrinsics
 @subsection RISC-V Vector Intrinsics
 
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c
index c5d78c1763d3..0d5b58c4fadf 100644
--- a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c
@@ -13,11 +13,13 @@ void foo (char *p)
   __builtin_prefetch (p, 1, 3);
 }
 
-int foo1()
+void foo1 ()
 {
-  return __builtin_riscv_zicbop_cbo_prefetchi(1);
+  __builtin_riscv_zicbop_prefetch_i(0);
+  __builtin_riscv_zicbop_prefetch_i(&foo);
+  __builtin_riscv_zicbop_prefetch_i((void*)0x111);
 }
 
-/* { dg-final { scan-assembler-times "prefetch.i" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch.i" 3 } } */
 /* { dg-final { scan-assembler-times "prefetch.r" 4 } } */
 /* { dg-final { scan-assembler-times "prefetch.w" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c
index 6576365b39ca..09655c4b8593 100644
--- a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c
@@ -13,11 +13,13 @@ void foo (char *p)
   __builtin_prefetch (p, 1, 3);
 }
 
-int foo1()
+void foo1 ()
 {
-  return __builtin_riscv_zicbop_cbo_prefetchi(1);
+  __builtin_riscv_zicbop_prefetch_i(0);
+  __builtin_riscv_zicbop_prefetch_i(&foo);
+  __builtin_riscv_zicbop_prefetch_i((void*)0x111);
 }
 
-/* { dg-final { scan-assembler-times "prefetch.i" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch.i" 3 } } */
 /* { dg-final { scan-assembler-times "prefetch.r" 4 } } */
-/* { dg-final { scan-assembler-times "prefetch.w" 4 } } */ 
+/* { dg-final { scan-assembler-times "prefetch.w" 4 } } */
-- 
2.41.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/1] RISC-V: Make "prefetch.i" built-in usable
  2023-08-10  3:10 ` [PATCH 1/1] " Tsukasa OI
@ 2023-08-28 21:20   ` Jeff Law
  2023-08-29  2:09     ` Tsukasa OI
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff Law @ 2023-08-28 21:20 UTC (permalink / raw)
  To: Tsukasa OI, Kito Cheng, Palmer Dabbelt, Andrew Waterman, Jim Wilson
  Cc: gcc-patches



On 8/9/23 21:10, Tsukasa OI via Gcc-patches wrote:
> From: Tsukasa OI <research_trasio@irq.a4lg.com>
> 
> The "__builtin_riscv_zicbop_cbo_prefetchi" built-in function was terribly
> broken so that practically unusable.  It emitted "prefetch.i" but with no
> meaningful arguments.
> 
> Though incompatible, this commit completely changes the function prototype
> of this built-in and makes it usable.  To minimize the functionality issues,
> it renames the built-in to "__builtin_riscv_zicbop_prefetch_i".
> 
> gcc/ChangeLog:
> 
> 	* config/riscv/riscv-cmo.def: Fix function prototype.
> 	* config/riscv/riscv.md (riscv_prefetchi_<mode>): Fix instruction
> 	prototype.  Remove possible prefectch type argument
> 	* doc/extend.texi: Document __builtin_riscv_zicbop_prefetch_i.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/riscv/cmo-zicbop-1.c: Reflect new built-in prototype.
> 	* gcc.target/riscv/cmo-zicbop-2.c: Likewise.
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index 688fd697255b..5658c7b7e113 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -3273,9 +3273,8 @@
>   })
>   
>   (define_insn "riscv_prefetchi_<mode>"
> -  [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
> -              (match_operand:X 1 "imm5_operand" "i")]
> -              UNSPECV_PREI)]
> +  [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
> +    UNSPECV_PREI)]
>     "TARGET_ZICBOP"
>     "prefetch.i\t%a0"
>   )
What I would suggest is making a new predicate that accepts either a 
register or a register+offset where the offset fits in a signed 12 bit 
immediate.  Use that for operand 0's predicate and I think this will 
"just work" and cover all the cases supported by the prefetch.i instruction.

Jeff

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/1] RISC-V: Make "prefetch.i" built-in usable
  2023-08-28 21:20   ` Jeff Law
@ 2023-08-29  2:09     ` Tsukasa OI
  2023-08-29 13:47       ` Jeff Law
  0 siblings, 1 reply; 5+ messages in thread
From: Tsukasa OI @ 2023-08-29  2:09 UTC (permalink / raw)
  To: Jeff Law, Kito Cheng, Palmer Dabbelt, Andrew Waterman, Jim Wilson
  Cc: gcc-patches

On 2023/08/29 6:20, Jeff Law wrote:
> 
> 
> On 8/9/23 21:10, Tsukasa OI via Gcc-patches wrote:
>> From: Tsukasa OI <research_trasio@irq.a4lg.com>
>>
>> The "__builtin_riscv_zicbop_cbo_prefetchi" built-in function was terribly
>> broken so that practically unusable.  It emitted "prefetch.i" but with no
>> meaningful arguments.
>>
>> Though incompatible, this commit completely changes the function
>> prototype
>> of this built-in and makes it usable.  To minimize the functionality
>> issues,
>> it renames the built-in to "__builtin_riscv_zicbop_prefetch_i".
>>
>> gcc/ChangeLog:
>>
>>     * config/riscv/riscv-cmo.def: Fix function prototype.
>>     * config/riscv/riscv.md (riscv_prefetchi_<mode>): Fix instruction
>>     prototype.  Remove possible prefectch type argument
>>     * doc/extend.texi: Document __builtin_riscv_zicbop_prefetch_i.
>>
>> gcc/testsuite/ChangeLog:
>>
>>     * gcc.target/riscv/cmo-zicbop-1.c: Reflect new built-in prototype.
>>     * gcc.target/riscv/cmo-zicbop-2.c: Likewise.
>> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
>> index 688fd697255b..5658c7b7e113 100644
>> --- a/gcc/config/riscv/riscv.md
>> +++ b/gcc/config/riscv/riscv.md
>> @@ -3273,9 +3273,8 @@
>>   })
>>     (define_insn "riscv_prefetchi_<mode>"
>> -  [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
>> -              (match_operand:X 1 "imm5_operand" "i")]
>> -              UNSPECV_PREI)]
>> +  [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
>> +    UNSPECV_PREI)]
>>     "TARGET_ZICBOP"
>>     "prefetch.i\t%a0"
>>   )
> What I would suggest is making a new predicate that accepts either a
> register or a register+offset where the offset fits in a signed 12 bit
> immediate.  Use that for operand 0's predicate and I think this will
> "just work" and cover all the cases supported by the prefetch.i
> instruction.
> 
> Jeff
> 

Seems reasonable.

If we have to break the compatibility anyway, adding an offset argument
is not a bad idea (though I think they will use inline assembly if a
non-zero offset is required).

I will try to add *optional* offset argument (with default value 0) like
 __builtin_speculation_safe_value built-in function in the next version.

Thanks,
Tsukasa

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/1] RISC-V: Make "prefetch.i" built-in usable
  2023-08-29  2:09     ` Tsukasa OI
@ 2023-08-29 13:47       ` Jeff Law
  0 siblings, 0 replies; 5+ messages in thread
From: Jeff Law @ 2023-08-29 13:47 UTC (permalink / raw)
  To: Tsukasa OI, Kito Cheng, Palmer Dabbelt, Andrew Waterman, Jim Wilson
  Cc: gcc-patches



On 8/28/23 20:09, Tsukasa OI wrote:
> On 2023/08/29 6:20, Jeff Law wrote:
>>
>>
>> On 8/9/23 21:10, Tsukasa OI via Gcc-patches wrote:
>>> From: Tsukasa OI <research_trasio@irq.a4lg.com>
>>>
>>> The "__builtin_riscv_zicbop_cbo_prefetchi" built-in function was terribly
>>> broken so that practically unusable.  It emitted "prefetch.i" but with no
>>> meaningful arguments.
>>>
>>> Though incompatible, this commit completely changes the function
>>> prototype
>>> of this built-in and makes it usable.  To minimize the functionality
>>> issues,
>>> it renames the built-in to "__builtin_riscv_zicbop_prefetch_i".
>>>
>>> gcc/ChangeLog:
>>>
>>>      * config/riscv/riscv-cmo.def: Fix function prototype.
>>>      * config/riscv/riscv.md (riscv_prefetchi_<mode>): Fix instruction
>>>      prototype.  Remove possible prefectch type argument
>>>      * doc/extend.texi: Document __builtin_riscv_zicbop_prefetch_i.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>>      * gcc.target/riscv/cmo-zicbop-1.c: Reflect new built-in prototype.
>>>      * gcc.target/riscv/cmo-zicbop-2.c: Likewise.
>>> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
>>> index 688fd697255b..5658c7b7e113 100644
>>> --- a/gcc/config/riscv/riscv.md
>>> +++ b/gcc/config/riscv/riscv.md
>>> @@ -3273,9 +3273,8 @@
>>>    })
>>>      (define_insn "riscv_prefetchi_<mode>"
>>> -  [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
>>> -              (match_operand:X 1 "imm5_operand" "i")]
>>> -              UNSPECV_PREI)]
>>> +  [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
>>> +    UNSPECV_PREI)]
>>>      "TARGET_ZICBOP"
>>>      "prefetch.i\t%a0"
>>>    )
>> What I would suggest is making a new predicate that accepts either a
>> register or a register+offset where the offset fits in a signed 12 bit
>> immediate.  Use that for operand 0's predicate and I think this will
>> "just work" and cover all the cases supported by the prefetch.i
>> instruction.
>>
>> Jeff
>>
> 
> Seems reasonable.
> 
> If we have to break the compatibility anyway, adding an offset argument
> is not a bad idea (though I think they will use inline assembly if a
> non-zero offset is required).
> 
> I will try to add *optional* offset argument (with default value 0) like
>   __builtin_speculation_safe_value built-in function in the next version.
The reason I suggested creating a predicate which allowed either a reg 
or reg+offset was to give that level of flexibility.

The inline assembly would specify an address.  If the address was 
already in a register, great.  If the address is expressable as 
reg+offset, also great.  If the address was a symbolic operand, the 
right predicate+constraint should force the symbolic into a register.

Jeff

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-08-29 13:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-10  3:10 [PATCH 0/1] RISC-V: Make "prefetch.i" built-in usable Tsukasa OI
2023-08-10  3:10 ` [PATCH 1/1] " Tsukasa OI
2023-08-28 21:20   ` Jeff Law
2023-08-29  2:09     ` Tsukasa OI
2023-08-29 13:47       ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).