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/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
--
2.41.0
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
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
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.
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.
© 2016 - 2026 Red Hat, Inc.