diff mbox series

[1/2] scripts/coccinelle: Add cpu_env.cocci_template script

Message ID 20240125165648.49898-2-philmd@linaro.org
State New
Headers show
Series hw, target: Prefer fast cpu_env() over slower CPU QOM cast macro | expand

Commit Message

Philippe Mathieu-Daudé Jan. 25, 2024, 4:56 p.m. UTC
Add a Coccinelle script to convert the following slow path
(due to the QOM cast macro):

  &ARCH_CPU(..)->env

to the following fast path:

  cpu_env(..)

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 MAINTAINERS                               |  1 +
 scripts/coccinelle/cpu_env.cocci_template | 60 +++++++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 scripts/coccinelle/cpu_env.cocci_template

Comments

Philippe Mathieu-Daudé Jan. 26, 2024, 10:38 a.m. UTC | #1
On 25/1/24 17:56, Philippe Mathieu-Daudé wrote:
> Add a Coccinelle script to convert the following slow path
> (due to the QOM cast macro):
> 
>    &ARCH_CPU(..)->env
> 
> to the following fast path:
> 
>    cpu_env(..)
> 
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
>   MAINTAINERS                               |  1 +
>   scripts/coccinelle/cpu_env.cocci_template | 60 +++++++++++++++++++++++
>   2 files changed, 61 insertions(+)
>   create mode 100644 scripts/coccinelle/cpu_env.cocci_template


> diff --git a/scripts/coccinelle/cpu_env.cocci_template b/scripts/coccinelle/cpu_env.cocci_template
> new file mode 100644
> index 0000000000..53aa3a1fea
> --- /dev/null
> +++ b/scripts/coccinelle/cpu_env.cocci_template
> @@ -0,0 +1,60 @@
> +/*
> +
> + Convert &ARCH_CPU(..)->env to use cpu_env(..).
> +
> + Rationale: ARCH_CPU() might be slow, being a QOM cast macro.
> +            cpu_env() is its fast equivalent.
> +
> + SPDX-License-Identifier: GPL-2.0-or-later
> + SPDX-FileCopyrightText: Linaro Ltd 2024
> + SPDX-FileContributor: Philippe Mathieu-Daudé
> +
> + Usage as of v8.2.0:
> +
> + $ for targetdir in target/*; do test -d $targetdir || continue; \
> +       export target=${targetdir:7}; \
> +       sed \
> +           -e "s/__CPUArchState__/$( \
> +               git grep -h --no-line-number '@env: #CPU.*State' \
> +                   target/$target/cpu.h \
> +               | sed -n -e 's/.*\(CPU.*State\).\?/\1/p')/g" \
> +           -e "s/__ARCHCPU__/$( \
> +               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
> +                   target/$target/cpu-qom.h \
> +               | sed -n -e 's/.*(\(.*\), .*, .*)/\1/p')/g" \
> +           -e "s/__ARCH_CPU__/$( \
> +               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
> +                   target/$target/cpu-qom.h \
> +               | sed -n -e 's/.*(.*, .*, \(.*\))/\1/p')/g" \
> +       < scripts/coccinelle/cpu_env.cocci_template \
> +       > $TMPDIR/cpu_env_$target.cocci; \
> +       for dir in hw target/$target; do \
> +           spatch --macro-file scripts/cocci-macro-file.h \
> +                  --sp-file $TMPDIR/cpu_env_$target.cocci \
> +                  --keep-comments \
> +                  --dir $dir \
> +                  --in-place; \
> +       done; \
> +   done
> +
> +*/
> +
> +@ CPUState_arg_used @
> +CPUState *cs;
> +identifier cpu;
> +identifier env;
> +@@
> +-   __ARCHCPU__ *cpu = __ARCH_CPU__(cs);

Here we remove ARCH_CPU(), ...

> +-   __CPUArchState__ *env = &cpu->env;
> ++   __CPUArchState__ *env = cpu_env(cs);
> +    ... when != cpu
> +
> +@ depends on never CPUState_arg_used @
> +identifier obj;
> +identifier cpu;
> +identifier env;
> +@@
> +-   __ARCHCPU__ *cpu = __ARCH_CPU__(obj);
> +-   __CPUArchState__ *env = &cpu->env;
> ++   __CPUArchState__ *env = cpu_env(CPU(obj));

... but here we just change it by a CPU() QOM call.
So this 2nd change is just style cleanup.

> +    ... when != cpu
Paolo Bonzini Jan. 26, 2024, 11:24 a.m. UTC | #2
On Fri, Jan 26, 2024 at 11:38 AM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 25/1/24 17:56, Philippe Mathieu-Daudé wrote:
> > Add a Coccinelle script to convert the following slow path
> > (due to the QOM cast macro):
> >
> >    &ARCH_CPU(..)->env
> >
> > to the following fast path:
> >
> >    cpu_env(..)
> >
> > Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> > ---
> >   MAINTAINERS                               |  1 +
> >   scripts/coccinelle/cpu_env.cocci_template | 60 +++++++++++++++++++++++
> >   2 files changed, 61 insertions(+)
> >   create mode 100644 scripts/coccinelle/cpu_env.cocci_template
>
>
> > diff --git a/scripts/coccinelle/cpu_env.cocci_template b/scripts/coccinelle/cpu_env.cocci_template
> > new file mode 100644
> > index 0000000000..53aa3a1fea
> > --- /dev/null
> > +++ b/scripts/coccinelle/cpu_env.cocci_template
> > @@ -0,0 +1,60 @@
> > +/*
> > +
> > + Convert &ARCH_CPU(..)->env to use cpu_env(..).
> > +
> > + Rationale: ARCH_CPU() might be slow, being a QOM cast macro.
> > +            cpu_env() is its fast equivalent.
> > +
> > + SPDX-License-Identifier: GPL-2.0-or-later
> > + SPDX-FileCopyrightText: Linaro Ltd 2024
> > + SPDX-FileContributor: Philippe Mathieu-Daudé
> > +
> > + Usage as of v8.2.0:
> > +
> > + $ for targetdir in target/*; do test -d $targetdir || continue; \
> > +       export target=${targetdir:7}; \
> > +       sed \
> > +           -e "s/__CPUArchState__/$( \
> > +               git grep -h --no-line-number '@env: #CPU.*State' \
> > +                   target/$target/cpu.h \
> > +               | sed -n -e 's/.*\(CPU.*State\).\?/\1/p')/g" \
> > +           -e "s/__ARCHCPU__/$( \
> > +               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
> > +                   target/$target/cpu-qom.h \
> > +               | sed -n -e 's/.*(\(.*\), .*, .*)/\1/p')/g" \
> > +           -e "s/__ARCH_CPU__/$( \
> > +               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
> > +                   target/$target/cpu-qom.h \
> > +               | sed -n -e 's/.*(.*, .*, \(.*\))/\1/p')/g" \
> > +       < scripts/coccinelle/cpu_env.cocci_template \
> > +       > $TMPDIR/cpu_env_$target.cocci; \
> > +       for dir in hw target/$target; do \
> > +           spatch --macro-file scripts/cocci-macro-file.h \
> > +                  --sp-file $TMPDIR/cpu_env_$target.cocci \
> > +                  --keep-comments \
> > +                  --dir $dir \
> > +                  --in-place; \
> > +       done; \
> > +   done
> > +
> > +*/
> > +
> > +@ CPUState_arg_used @
> > +CPUState *cs;
> > +identifier cpu;
> > +identifier env;
> > +@@
> > +-   __ARCHCPU__ *cpu = __ARCH_CPU__(cs);
>
> Here we remove ARCH_CPU(), ...
>
> > +-   __CPUArchState__ *env = &cpu->env;
> > ++   __CPUArchState__ *env = cpu_env(cs);
> > +    ... when != cpu
> > +
> > +@ depends on never CPUState_arg_used @
> > +identifier obj;
> > +identifier cpu;
> > +identifier env;
> > +@@
> > +-   __ARCHCPU__ *cpu = __ARCH_CPU__(obj);
> > +-   __CPUArchState__ *env = &cpu->env;
> > ++   __CPUArchState__ *env = cpu_env(CPU(obj));
>
> ... but here we just change it by a CPU() QOM call.
> So this 2nd change is just style cleanup.

Can you also add a hunk that is

CPUState *cs;
@@
-  CPU(cs)
+ cs

to clean up on the second?  cpu_env(CPU(current_cpu)) is suboptimal
and also a bit ugly.

paolo
Philippe Mathieu-Daudé Jan. 26, 2024, 12:34 p.m. UTC | #3
On 26/1/24 12:24, Paolo Bonzini wrote:
> On Fri, Jan 26, 2024 at 11:38 AM Philippe Mathieu-Daudé
> <philmd@linaro.org> wrote:
>>
>> On 25/1/24 17:56, Philippe Mathieu-Daudé wrote:
>>> Add a Coccinelle script to convert the following slow path
>>> (due to the QOM cast macro):
>>>
>>>     &ARCH_CPU(..)->env
>>>
>>> to the following fast path:
>>>
>>>     cpu_env(..)
>>>
>>> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>>> ---
>>>    MAINTAINERS                               |  1 +
>>>    scripts/coccinelle/cpu_env.cocci_template | 60 +++++++++++++++++++++++
>>>    2 files changed, 61 insertions(+)
>>>    create mode 100644 scripts/coccinelle/cpu_env.cocci_template
>>
>>
>>> diff --git a/scripts/coccinelle/cpu_env.cocci_template b/scripts/coccinelle/cpu_env.cocci_template
>>> new file mode 100644
>>> index 0000000000..53aa3a1fea
>>> --- /dev/null
>>> +++ b/scripts/coccinelle/cpu_env.cocci_template
>>> @@ -0,0 +1,60 @@
>>> +/*
>>> +
>>> + Convert &ARCH_CPU(..)->env to use cpu_env(..).
>>> +
>>> + Rationale: ARCH_CPU() might be slow, being a QOM cast macro.
>>> +            cpu_env() is its fast equivalent.
>>> +
>>> + SPDX-License-Identifier: GPL-2.0-or-later
>>> + SPDX-FileCopyrightText: Linaro Ltd 2024
>>> + SPDX-FileContributor: Philippe Mathieu-Daudé
>>> +
>>> + Usage as of v8.2.0:
>>> +
>>> + $ for targetdir in target/*; do test -d $targetdir || continue; \
>>> +       export target=${targetdir:7}; \
>>> +       sed \
>>> +           -e "s/__CPUArchState__/$( \
>>> +               git grep -h --no-line-number '@env: #CPU.*State' \
>>> +                   target/$target/cpu.h \
>>> +               | sed -n -e 's/.*\(CPU.*State\).\?/\1/p')/g" \
>>> +           -e "s/__ARCHCPU__/$( \
>>> +               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
>>> +                   target/$target/cpu-qom.h \
>>> +               | sed -n -e 's/.*(\(.*\), .*, .*)/\1/p')/g" \
>>> +           -e "s/__ARCH_CPU__/$( \
>>> +               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
>>> +                   target/$target/cpu-qom.h \
>>> +               | sed -n -e 's/.*(.*, .*, \(.*\))/\1/p')/g" \
>>> +       < scripts/coccinelle/cpu_env.cocci_template \
>>> +       > $TMPDIR/cpu_env_$target.cocci; \
>>> +       for dir in hw target/$target; do \
>>> +           spatch --macro-file scripts/cocci-macro-file.h \
>>> +                  --sp-file $TMPDIR/cpu_env_$target.cocci \
>>> +                  --keep-comments \
>>> +                  --dir $dir \
>>> +                  --in-place; \
>>> +       done; \
>>> +   done
>>> +
>>> +*/
>>> +
>>> +@ CPUState_arg_used @
>>> +CPUState *cs;
>>> +identifier cpu;
>>> +identifier env;
>>> +@@
>>> +-   __ARCHCPU__ *cpu = __ARCH_CPU__(cs);
>>
>> Here we remove ARCH_CPU(), ...
>>
>>> +-   __CPUArchState__ *env = &cpu->env;
>>> ++   __CPUArchState__ *env = cpu_env(cs);
>>> +    ... when != cpu
>>> +
>>> +@ depends on never CPUState_arg_used @
>>> +identifier obj;
>>> +identifier cpu;
>>> +identifier env;
>>> +@@
>>> +-   __ARCHCPU__ *cpu = __ARCH_CPU__(obj);
>>> +-   __CPUArchState__ *env = &cpu->env;
>>> ++   __CPUArchState__ *env = cpu_env(CPU(obj));
>>
>> ... but here we just change it by a CPU() QOM call.
>> So this 2nd change is just style cleanup.
> 
> Can you also add a hunk that is
> 
> CPUState *cs;
> @@
> -  CPU(cs)
> + cs
> 
> to clean up on the second?  cpu_env(CPU(current_cpu)) is suboptimal
> and also a bit ugly.

These case should be cleaned because this is already a CPUState*:

+    CPUX86State *env = cpu_env(CPU(current_cpu));

+    CPUPPCState *env = cpu_env(CPU(first_cpu));

But these (instance_init and QOM visitors) can't, the argument
isn't a CPUState*:

  static void ev4_cpu_initfn(Object *obj)
  {
-    AlphaCPU *cpu = ALPHA_CPU(obj);
-    CPUAlphaState *env = &cpu->env;
+    CPUAlphaState *env = cpu_env(CPU(obj));

@@ -5186,8 +5179,7 @@ static char *x86_cpuid_get_vendor(Object *obj, 
Error **errp)
  static void x86_cpuid_set_vendor(Object *obj, const char *value,
                                   Error **errp)
  {
-    X86CPU *cpu = X86_CPU(obj);
-    CPUX86State *env = &cpu->env;
+    CPUX86State *env = cpu_env(CPU(obj));

That said, these visitors take a Object* param because they implement
the generic QOM visitor API, but we know the visitor are registered
on classes/objects implementing CPUState, so QOM cast macro is
redundant.
Philippe Mathieu-Daudé Jan. 26, 2024, 1:50 p.m. UTC | #4
On 26/1/24 13:34, Philippe Mathieu-Daudé wrote:
> On 26/1/24 12:24, Paolo Bonzini wrote:
>> On Fri, Jan 26, 2024 at 11:38 AM Philippe Mathieu-Daudé
>> <philmd@linaro.org> wrote:
>>>
>>> On 25/1/24 17:56, Philippe Mathieu-Daudé wrote:
>>>> Add a Coccinelle script to convert the following slow path
>>>> (due to the QOM cast macro):
>>>>
>>>>     &ARCH_CPU(..)->env
>>>>
>>>> to the following fast path:
>>>>
>>>>     cpu_env(..)
>>>>
>>>> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>>>> ---
>>>>    MAINTAINERS                               |  1 +
>>>>    scripts/coccinelle/cpu_env.cocci_template | 60 
>>>> +++++++++++++++++++++++
>>>>    2 files changed, 61 insertions(+)
>>>>    create mode 100644 scripts/coccinelle/cpu_env.cocci_template
>>>
>>>
>>>> diff --git a/scripts/coccinelle/cpu_env.cocci_template 
>>>> b/scripts/coccinelle/cpu_env.cocci_template
>>>> new file mode 100644
>>>> index 0000000000..53aa3a1fea
>>>> --- /dev/null
>>>> +++ b/scripts/coccinelle/cpu_env.cocci_template
>>>> @@ -0,0 +1,60 @@
>>>> +/*
>>>> +
>>>> + Convert &ARCH_CPU(..)->env to use cpu_env(..).
>>>> +
>>>> + Rationale: ARCH_CPU() might be slow, being a QOM cast macro.
>>>> +            cpu_env() is its fast equivalent.
>>>> +
>>>> + SPDX-License-Identifier: GPL-2.0-or-later
>>>> + SPDX-FileCopyrightText: Linaro Ltd 2024
>>>> + SPDX-FileContributor: Philippe Mathieu-Daudé
>>>> +
>>>> + Usage as of v8.2.0:
>>>> +
>>>> + $ for targetdir in target/*; do test -d $targetdir || continue; \
>>>> +       export target=${targetdir:7}; \
>>>> +       sed \
>>>> +           -e "s/__CPUArchState__/$( \
>>>> +               git grep -h --no-line-number '@env: #CPU.*State' \
>>>> +                   target/$target/cpu.h \
>>>> +               | sed -n -e 's/.*\(CPU.*State\).\?/\1/p')/g" \
>>>> +           -e "s/__ARCHCPU__/$( \
>>>> +               git grep -h --no-line-number 
>>>> OBJECT_DECLARE_CPU_TYPE.*CPU \
>>>> +                   target/$target/cpu-qom.h \
>>>> +               | sed -n -e 's/.*(\(.*\), .*, .*)/\1/p')/g" \
>>>> +           -e "s/__ARCH_CPU__/$( \
>>>> +               git grep -h --no-line-number 
>>>> OBJECT_DECLARE_CPU_TYPE.*CPU \
>>>> +                   target/$target/cpu-qom.h \
>>>> +               | sed -n -e 's/.*(.*, .*, \(.*\))/\1/p')/g" \
>>>> +       < scripts/coccinelle/cpu_env.cocci_template \
>>>> +       > $TMPDIR/cpu_env_$target.cocci; \
>>>> +       for dir in hw target/$target; do \
>>>> +           spatch --macro-file scripts/cocci-macro-file.h \
>>>> +                  --sp-file $TMPDIR/cpu_env_$target.cocci \
>>>> +                  --keep-comments \
>>>> +                  --dir $dir \
>>>> +                  --in-place; \
>>>> +       done; \
>>>> +   done
>>>> +
>>>> +*/
>>>> +
>>>> +@ CPUState_arg_used @
>>>> +CPUState *cs;
>>>> +identifier cpu;
>>>> +identifier env;
>>>> +@@
>>>> +-   __ARCHCPU__ *cpu = __ARCH_CPU__(cs);
>>>
>>> Here we remove ARCH_CPU(), ...
>>>
>>>> +-   __CPUArchState__ *env = &cpu->env;
>>>> ++   __CPUArchState__ *env = cpu_env(cs);
>>>> +    ... when != cpu
>>>> +
>>>> +@ depends on never CPUState_arg_used @
>>>> +identifier obj;
>>>> +identifier cpu;
>>>> +identifier env;
>>>> +@@
>>>> +-   __ARCHCPU__ *cpu = __ARCH_CPU__(obj);
>>>> +-   __CPUArchState__ *env = &cpu->env;
>>>> ++   __CPUArchState__ *env = cpu_env(CPU(obj));
>>>
>>> ... but here we just change it by a CPU() QOM call.
>>> So this 2nd change is just style cleanup.
>>
>> Can you also add a hunk that is
>>
>> CPUState *cs;
>> @@
>> -  CPU(cs)
>> + cs
>>
>> to clean up on the second?  cpu_env(CPU(current_cpu)) is suboptimal
>> and also a bit ugly.
> 
> These case should be cleaned because this is already a CPUState*:
> 
> +    CPUX86State *env = cpu_env(CPU(current_cpu));
> 
> +    CPUPPCState *env = cpu_env(CPU(first_cpu));
> 
> But these (instance_init and QOM visitors) can't, the argument
> isn't a CPUState*:
> 
>   static void ev4_cpu_initfn(Object *obj)
>   {
> -    AlphaCPU *cpu = ALPHA_CPU(obj);
> -    CPUAlphaState *env = &cpu->env;
> +    CPUAlphaState *env = cpu_env(CPU(obj));
> 
> @@ -5186,8 +5179,7 @@ static char *x86_cpuid_get_vendor(Object *obj, 
> Error **errp)
>   static void x86_cpuid_set_vendor(Object *obj, const char *value,
>                                    Error **errp)
>   {
> -    X86CPU *cpu = X86_CPU(obj);
> -    CPUX86State *env = &cpu->env;
> +    CPUX86State *env = cpu_env(CPU(obj));
> 
> That said, these visitors take a Object* param because they implement
> the generic QOM visitor API, but we know the visitor are registered
> on classes/objects implementing CPUState, so QOM cast macro is
> redundant.

Bah actually for CPU() this is not a problem, per commit 0d6d1ab499
("cpu: Avoid QOM casts for CPU()") you suggested :)

     Keep the CPU() macro for a consistent developer experience and for
     flexibility to exchange its implementation, but turn it into a pure,
     unchecked C cast for now.
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index dfaca8323e..1d57130ff8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -157,6 +157,7 @@  F: accel/tcg/
 F: accel/stubs/tcg-stub.c
 F: util/cacheinfo.c
 F: util/cacheflush.c
+F: scripts/coccinelle/cpu_env.cocci_template
 F: scripts/decodetree.py
 F: docs/devel/decodetree.rst
 F: docs/devel/tcg*
diff --git a/scripts/coccinelle/cpu_env.cocci_template b/scripts/coccinelle/cpu_env.cocci_template
new file mode 100644
index 0000000000..53aa3a1fea
--- /dev/null
+++ b/scripts/coccinelle/cpu_env.cocci_template
@@ -0,0 +1,60 @@ 
+/*
+
+ Convert &ARCH_CPU(..)->env to use cpu_env(..).
+
+ Rationale: ARCH_CPU() might be slow, being a QOM cast macro.
+            cpu_env() is its fast equivalent.
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+ SPDX-FileCopyrightText: Linaro Ltd 2024
+ SPDX-FileContributor: Philippe Mathieu-Daudé
+
+ Usage as of v8.2.0:
+
+ $ for targetdir in target/*; do test -d $targetdir || continue; \
+       export target=${targetdir:7}; \
+       sed \
+           -e "s/__CPUArchState__/$( \
+               git grep -h --no-line-number '@env: #CPU.*State' \
+                   target/$target/cpu.h \
+               | sed -n -e 's/.*\(CPU.*State\).\?/\1/p')/g" \
+           -e "s/__ARCHCPU__/$( \
+               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
+                   target/$target/cpu-qom.h \
+               | sed -n -e 's/.*(\(.*\), .*, .*)/\1/p')/g" \
+           -e "s/__ARCH_CPU__/$( \
+               git grep -h --no-line-number OBJECT_DECLARE_CPU_TYPE.*CPU \
+                   target/$target/cpu-qom.h \
+               | sed -n -e 's/.*(.*, .*, \(.*\))/\1/p')/g" \
+       < scripts/coccinelle/cpu_env.cocci_template \
+       > $TMPDIR/cpu_env_$target.cocci; \
+       for dir in hw target/$target; do \
+           spatch --macro-file scripts/cocci-macro-file.h \
+                  --sp-file $TMPDIR/cpu_env_$target.cocci \
+                  --keep-comments \
+                  --dir $dir \
+                  --in-place; \
+       done; \
+   done
+
+*/
+
+@ CPUState_arg_used @
+CPUState *cs;
+identifier cpu;
+identifier env;
+@@
+-   __ARCHCPU__ *cpu = __ARCH_CPU__(cs);
+-   __CPUArchState__ *env = &cpu->env;
++   __CPUArchState__ *env = cpu_env(cs);
+    ... when != cpu
+
+@ depends on never CPUState_arg_used @
+identifier obj;
+identifier cpu;
+identifier env;
+@@
+-   __ARCHCPU__ *cpu = __ARCH_CPU__(obj);
+-   __CPUArchState__ *env = &cpu->env;
++   __CPUArchState__ *env = cpu_env(CPU(obj));
+    ... when != cpu