Now we have eliminated all uses of vm_area_desc->vm_flags, eliminate this
field, and have mmap_prepare users utilise the vma_flags_t
vm_area_desc->vma_flags field only.
As part of this change we alter is_shared_maywrite() to accept a
vma_flags_t parameter, and introduce is_shared_maywrite_vm_flags() for use
with legacy vm_flags_t flags.
We also update struct mmap_state to add a union between vma_flags and
vm_flags temporarily until the mmap logic is also converted to using
vma_flags_t.
Also update the VMA userland tests to reflect this change.
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
include/linux/mm.h | 9 +++++++--
include/linux/mm_types.h | 5 +----
mm/filemap.c | 2 +-
mm/util.c | 2 +-
mm/vma.c | 11 +++++++----
mm/vma.h | 3 +--
tools/testing/vma/vma_internal.h | 9 +++++++--
7 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 32f48d5a28ce..407fcdc4831d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1293,15 +1293,20 @@ static inline bool vma_is_accessible(const struct vm_area_struct *vma)
return vma->vm_flags & VM_ACCESS_FLAGS;
}
-static inline bool is_shared_maywrite(vm_flags_t vm_flags)
+static inline bool is_shared_maywrite_vm_flags(vm_flags_t vm_flags)
{
return (vm_flags & (VM_SHARED | VM_MAYWRITE)) ==
(VM_SHARED | VM_MAYWRITE);
}
+static inline bool is_shared_maywrite(vma_flags_t flags)
+{
+ return vma_flags_test_all(flags, VMA_SHARED_BIT, VMA_MAYWRITE_BIT);
+}
+
static inline bool vma_is_shared_maywrite(const struct vm_area_struct *vma)
{
- return is_shared_maywrite(vma->vm_flags);
+ return is_shared_maywrite(vma->flags);
}
static inline
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index c3589bc3780e..5042374d854b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -877,10 +877,7 @@ struct vm_area_desc {
/* Mutable fields. Populated with initial state. */
pgoff_t pgoff;
struct file *vm_file;
- union {
- vm_flags_t vm_flags;
- vma_flags_t vma_flags;
- };
+ vma_flags_t vma_flags;
pgprot_t page_prot;
/* Write-only fields. */
diff --git a/mm/filemap.c b/mm/filemap.c
index ebd75684cb0a..109a4bf07366 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -4012,7 +4012,7 @@ int generic_file_readonly_mmap(struct file *file, struct vm_area_struct *vma)
int generic_file_readonly_mmap_prepare(struct vm_area_desc *desc)
{
- if (is_shared_maywrite(desc->vm_flags))
+ if (is_shared_maywrite(desc->vma_flags))
return -EINVAL;
return generic_file_mmap_prepare(desc);
}
diff --git a/mm/util.c b/mm/util.c
index 97cae40c0209..b05ab6f97e11 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1154,7 +1154,7 @@ int __compat_vma_mmap(const struct file_operations *f_op,
.pgoff = vma->vm_pgoff,
.vm_file = vma->vm_file,
- .vm_flags = vma->vm_flags,
+ .vma_flags = vma->flags,
.page_prot = vma->vm_page_prot,
.action.type = MMAP_NOTHING, /* Default */
diff --git a/mm/vma.c b/mm/vma.c
index 39dcd9ddd4ba..be64f781a3aa 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -15,7 +15,10 @@ struct mmap_state {
unsigned long end;
pgoff_t pgoff;
unsigned long pglen;
- vm_flags_t vm_flags;
+ union {
+ vm_flags_t vm_flags;
+ vma_flags_t vma_flags;
+ };
struct file *file;
pgprot_t page_prot;
@@ -2369,7 +2372,7 @@ static void set_desc_from_map(struct vm_area_desc *desc,
desc->pgoff = map->pgoff;
desc->vm_file = map->file;
- desc->vm_flags = map->vm_flags;
+ desc->vma_flags = map->vma_flags;
desc->page_prot = map->page_prot;
}
@@ -2650,7 +2653,7 @@ static int call_mmap_prepare(struct mmap_state *map,
map->file_doesnt_need_get = true;
map->file = desc->vm_file;
}
- map->vm_flags = desc->vm_flags;
+ map->vma_flags = desc->vma_flags;
map->page_prot = desc->page_prot;
/* User-defined fields. */
map->vm_ops = desc->vm_ops;
@@ -2823,7 +2826,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
return -EINVAL;
/* Map writable and ensure this isn't a sealed memfd. */
- if (file && is_shared_maywrite(vm_flags)) {
+ if (file && is_shared_maywrite_vm_flags(vm_flags)) {
int error = mapping_map_writable(file->f_mapping);
if (error)
diff --git a/mm/vma.h b/mm/vma.h
index bb7fa5d2bde2..062672df8a65 100644
--- a/mm/vma.h
+++ b/mm/vma.h
@@ -286,8 +286,7 @@ static inline void set_vma_from_desc(struct vm_area_struct *vma,
vma->vm_pgoff = desc->pgoff;
if (desc->vm_file != vma->vm_file)
vma_set_file(vma, desc->vm_file);
- if (desc->vm_flags != vma->vm_flags)
- vm_flags_set(vma, desc->vm_flags);
+ vma->flags = desc->vma_flags;
vma->vm_page_prot = desc->page_prot;
/* User-defined fields. */
diff --git a/tools/testing/vma/vma_internal.h b/tools/testing/vma/vma_internal.h
index 1ac81a09feb8..8143b95dc50e 100644
--- a/tools/testing/vma/vma_internal.h
+++ b/tools/testing/vma/vma_internal.h
@@ -1009,15 +1009,20 @@ static inline void vma_desc_clear_flags_mask(struct vm_area_desc *desc,
#define vma_desc_clear_flags(desc, ...) \
vma_desc_clear_flags_mask(desc, mk_vma_flags(__VA_ARGS__))
-static inline bool is_shared_maywrite(vm_flags_t vm_flags)
+static inline bool is_shared_maywrite_vm_flags(vm_flags_t vm_flags)
{
return (vm_flags & (VM_SHARED | VM_MAYWRITE)) ==
(VM_SHARED | VM_MAYWRITE);
}
+static inline bool is_shared_maywrite(vma_flags_t flags)
+{
+ return vma_flags_test_all(flags, VMA_SHARED_BIT, VMA_MAYWRITE_BIT);
+}
+
static inline bool vma_is_shared_maywrite(struct vm_area_struct *vma)
{
- return is_shared_maywrite(vma->vm_flags);
+ return is_shared_maywrite(vma->flags);
}
static inline struct vm_area_struct *vma_next(struct vma_iterator *vmi)
--
2.52.0
On Mon, Jan 19, 2026 at 09:19:11PM +0000, Lorenzo Stoakes wrote:
> +static inline bool is_shared_maywrite(vma_flags_t flags)
> +{
I'm not sure it is ideal to pass this array by value? Seems like it
might invite some negative optimizations since now the compiler has to
optimze away a copy too.
Jason
On Mon, Jan 19, 2026 at 07:14:03PM -0400, Jason Gunthorpe wrote:
> On Mon, Jan 19, 2026 at 09:19:11PM +0000, Lorenzo Stoakes wrote:
> > +static inline bool is_shared_maywrite(vma_flags_t flags)
> > +{
>
> I'm not sure it is ideal to pass this array by value? Seems like it
> might invite some negative optimizations since now the compiler has to
> optimze away a copy too.
I really don't think so? This is inlined and thus collapses to a totally
standard vma_flags_test_all() which passes by value anyway.
Which is in itself passing-an-array-by-value, and also inlined (though we force
the inline).
I have done a bunch of assembly generation and it has all indicated the compiler
handles this perfectly well.
It in fact is the basis of being able to pretty well like-for-like replace
vm_flags_t with vma_flags_t which makes the transition significantly better (and
allows for the mk_vma_flags() helper and associated helper macros).
Do you have specific examples or evidence the compiler will optimise poorly here
on that basis as compared to pass by reference? And pass by reference would
necessitate:
vma_flags_test_all(*flags, ...);
Or changing the whole approach? My experience generating assembly doesn't
suggest any of this is necessary.
Explicitly for this case, generating the invocation from
generic_file_readonly_mmap_prepare():
if (is_shared_maywrite(desc->vma_flags))
return -EINVAL;
Is:
notl %ecx
testb $40, %cl
je .LBB106_6 [ return -EINVAL ]
In this implementation and:
notl %ecx
testb $40, %cl
je .LBB106_6 [ return -EINVAL ]
Without my series (I am omitting movl $-22, %eax in both as this just sets up
the -EINVAL return).
i.e. exactly identical.
My experience so far is this is _always_ the case, the compiler is very adept at
optimising these kinds of things.
Thanks, Lorenzo
On Tue, Jan 20, 2026 at 09:46:05AM +0000, Lorenzo Stoakes wrote:
> On Mon, Jan 19, 2026 at 07:14:03PM -0400, Jason Gunthorpe wrote:
> > On Mon, Jan 19, 2026 at 09:19:11PM +0000, Lorenzo Stoakes wrote:
> > > +static inline bool is_shared_maywrite(vma_flags_t flags)
> > > +{
> >
> > I'm not sure it is ideal to pass this array by value? Seems like it
> > might invite some negative optimizations since now the compiler has to
> > optimze away a copy too.
>
> I really don't think so? This is inlined and thus collapses to a totally
> standard vma_flags_test_all() which passes by value anyway.
> Do you have specific examples or evidence the compiler will optimise poorly here
> on that basis as compared to pass by reference? And pass by reference would
> necessitate:
I've recently seen enough cases of older compilers and other arches
making weird choices to be a little concerened. In the above case
there is no reason not to use a const pointer (and indeed that would
be the expected idomatic kernel style), so why take chances is my
thinking.
Jason
On Tue, Jan 20, 2026 at 09:36:19AM -0400, Jason Gunthorpe wrote:
> On Tue, Jan 20, 2026 at 09:46:05AM +0000, Lorenzo Stoakes wrote:
> > On Mon, Jan 19, 2026 at 07:14:03PM -0400, Jason Gunthorpe wrote:
> > > On Mon, Jan 19, 2026 at 09:19:11PM +0000, Lorenzo Stoakes wrote:
> > > > +static inline bool is_shared_maywrite(vma_flags_t flags)
> > > > +{
> > >
> > > I'm not sure it is ideal to pass this array by value? Seems like it
> > > might invite some negative optimizations since now the compiler has to
> > > optimze away a copy too.
> >
> > I really don't think so? This is inlined and thus collapses to a totally
> > standard vma_flags_test_all() which passes by value anyway.
>
> > Do you have specific examples or evidence the compiler will optimise poorly here
> > on that basis as compared to pass by reference? And pass by reference would
> > necessitate:
>
> I've recently seen enough cases of older compilers and other arches
> making weird choices to be a little concerened. In the above case
> there is no reason not to use a const pointer (and indeed that would
> be the expected idomatic kernel style), so why take chances is my
> thinking.
With respect Jason, you're going to have to do better than that.
The entire implementation is dependent on passing-by-value.
Right now we can do:
vma_flags_test(&flags, VMA_READ_BIT, VMA_WRITE_BIT, ...);
Which uses mk_vma_flags() in a macro to generalise to:
vma_flags_test(&flags, <vma_flags_t value>);
The natural implication of what you're saying is that we can no longer use this
from _anywhere_ because - hey - passing this by value is bad so now _everything_
has to be re-written as:
vma_flags_t flags_to_set = mk_vma_flags(<flags>);
if (vma_flags_test(&flags, &flags_to_set)) { ... }
Right?
But is even that ok? Because presumably these compilers can inline, so that is
basically equivalent to what the macro's doing so does that rule out the VMA
bitmap flags concept altogether...
For hand-waved 'old compilers' (ok, people who use old compilers should not
expect optimal code) or 'other arches' (unspecified)?
If it was just changing this one function I'd still object as it makes it differ
from _every other test predicate_ using vma_flags_t but maybe to humour you I'd
change it, but surely by this argument you're essentially objecting to the whole
series?
I find it really strange you're going down this road as it was you who suggested
this approach in the first place and had to convince me the compiler would
manage it!...
Maybe I'm missing something here...
I am not sure about this 'idiomatic kernel style' thing either, it feels rather
conjured. Yes you wouldn't ordinarily pass something larger than a register size
by-value, but here the intent is for it to be inlined anyway right?
It strikes me that the key optimisation here is the inlining, now if the issue
is that ye olde compiler might choose not to inline very small functions (seems
unlikely) we could always throw in an __always_inline?
But it seems rather silly for a one-liner?
If the concern is deeper (not optimising the bitmap operations) then aren't you
saying no to the whole concept of the series?
Out of interest I godbolted a bunch of architectures:
x86-64
riscv
mips
s390x
sparc
arm7 32-bit
loongarch
m68k
xtensa
And found the manual method vs. the pass-by-value macro method were equivalent
in each case as far as I could tell.
In the worst case if we hit a weirdo case we can always substitute something
manual I have all the vma_flags_*word*() stuff available (which I recall you
objecting to...!)
I may have completely the wrong end of the stick here?...
>
> Jason
Thanks, Lorenzo
On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote:
> On Tue, Jan 20, 2026 at 09:36:19AM -0400, Jason Gunthorpe wrote:
>
> I am not sure about this 'idiomatic kernel style' thing either, it feels rather
> conjured. Yes you wouldn't ordinarily pass something larger than a register size
> by-value, but here the intent is for it to be inlined anyway right?
>
> It strikes me that the key optimisation here is the inlining, now if the issue
> is that ye olde compiler might choose not to inline very small functions (seems
> unlikely) we could always throw in an __always_inline?
I can think of three specific things going wrong with structures passed
by value:
- functions that cannot be inlined are bound by the ELF ABI, and
several of them require structs to be passed on the stack regardless
of the size. Most of the popular architectures seem fine here, but
mips and powerpc look like they are affected.
- The larger the struct is, the more architectures are affected.
Parts of the amdgpu driver and the bcachefs file system ran into this
with 64-bit structures passed by value on 32-bit architectures
causing horrible codegen even with inlining. I think it's
usually fine up to a single register size.
- clang's inlining algorithm works the other way round from gcc's:
inlining into the root caller first and sometimes leaving tiny
leaf function out of line unless you add __always_inline.
Arnd
On Tue, Jan 20, 2026 at 05:00:28PM +0100, Arnd Bergmann wrote: > On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote: > > On Tue, Jan 20, 2026 at 09:36:19AM -0400, Jason Gunthorpe wrote: > > > > I am not sure about this 'idiomatic kernel style' thing either, it feels rather > > conjured. Yes you wouldn't ordinarily pass something larger than a register size > > by-value, but here the intent is for it to be inlined anyway right? > > > > It strikes me that the key optimisation here is the inlining, now if the issue > > is that ye olde compiler might choose not to inline very small functions (seems > > unlikely) we could always throw in an __always_inline? > > I can think of three specific things going wrong with structures passed > by value: I mean now you seem to be talking about it _in general_ which, _in theory_, kills the whole concept of bitmap VMA flags _altogether_ really, or at least any workable version of them. But... no. I'm not going to not do this because of perceived possible issues with ppc and mips. It's not reasonable to hold up a necessary change for the future of the kernel IMO, and we can find workarounds as necessary should anything problematic actually occur in practice. I am happy to do so as maintainer of this work :) > > - functions that cannot be inlined are bound by the ELF ABI, and > several of them require structs to be passed on the stack regardless > of the size. Most of the popular architectures seem fine here, but > mips and powerpc look like they are affected. I explicitly checked mips and it seemed fine, but not gone super deep. > > - The larger the struct is, the more architectures are affected. > Parts of the amdgpu driver and the bcachefs file system ran into this bcachefs is not in the kernel. We don't care about out-of-tree stuff by convention. amdgpu is more concerning, but... > with 64-bit structures passed by value on 32-bit architectures > causing horrible codegen even with inlining. I think it's > usually fine up to a single register size. ...32-bit kernels are not ones where you would anticipate incredible performance for one, for another if any significant issues arise we can look at arch-specific workarounds. I already have vma_flags_*_word*() helpers to do things 'the old way' in the worst case. More can be added if and when anything arises. Again, I don't think we should hold up the rest of the kernel (being able to transition to not being arbitrarily limited by VMA count is very important) on this basis. Also I've checked 32-bit code generation which _seemed_ fine at a glance. Of course again I've not good super deep on that. > > - clang's inlining algorithm works the other way round from gcc's: > inlining into the root caller first and sometimes leaving tiny > leaf function out of line unless you add __always_inline. I already __always_inline all pertinent funcitons so hopefully that should be no issue. And for instance the assembly I shared earlier was built using clang, as I now use clang for _all_ my builds locally. > > Arnd Thanks, Lorenzo
On Tue, Jan 20, 2026, at 17:22, Lorenzo Stoakes wrote:
> On Tue, Jan 20, 2026 at 05:00:28PM +0100, Arnd Bergmann wrote:
>> On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote:
>> >
>> > It strikes me that the key optimisation here is the inlining, now if the issue
>> > is that ye olde compiler might choose not to inline very small functions (seems
>> > unlikely) we could always throw in an __always_inline?
>>
>> I can think of three specific things going wrong with structures passed
>> by value:
>
> I mean now you seem to be talking about it _in general_ which, _in theory_,
> kills the whole concept of bitmap VMA flags _altogether_ really, or at
> least any workable version of them.
No, what I'm saying is "understand what the pitfalls are", not
"don't do it". I think that is what Jason was also getting at.
Arnd
On Tue, Jan 20, 2026 at 05:44:29PM +0100, Arnd Bergmann wrote: > On Tue, Jan 20, 2026, at 17:22, Lorenzo Stoakes wrote: > > On Tue, Jan 20, 2026 at 05:00:28PM +0100, Arnd Bergmann wrote: > >> On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote: > >> > > >> > It strikes me that the key optimisation here is the inlining, now if the issue > >> > is that ye olde compiler might choose not to inline very small functions (seems > >> > unlikely) we could always throw in an __always_inline? > >> > >> I can think of three specific things going wrong with structures passed > >> by value: > > > > I mean now you seem to be talking about it _in general_ which, _in theory_, > > kills the whole concept of bitmap VMA flags _altogether_ really, or at > > least any workable version of them. > > No, what I'm saying is "understand what the pitfalls are", not > "don't do it". I think that is what Jason was also getting at. > > Arnd Ack sure and your input is appreciated :) It's important to kick the tyres and be aware of possible issues. Actually I think now I understand where Jason's coming from - the by-value cases will be const value for the most part - which should make life MUCH easier for the compiler and avoid a lot of the issues you raised. So _hopefully_ we're mitigated. Again as I said, in cases where we might not be, I will take action to figure out workarounds. I'm excited by the proposed approach in general (+ again thanks to Jason to opening my eyes to the possibility in the first place), so perhaps a _little_ defensive, as it allows for a like-for-like replacement generally which should HUGELY speed up + simplify the transition :) Cheers, Lorenzo
On Tue, Jan 20, 2026 at 03:10:54PM +0000, Lorenzo Stoakes wrote:
> The natural implication of what you're saying is that we can no longer use this
> from _anywhere_ because - hey - passing this by value is bad so now _everything_
> has to be re-written as:
No, I'm not saying that, I'm saying this specific case where you are
making an accessor to reach an unknown value located on the heap
should be using a pointer as both a matter of style and to simplify
life for the compiler.
> vma_flags_t flags_to_set = mk_vma_flags(<flags>);
>
> if (vma_flags_test(&flags, &flags_to_set)) { ... }
This is quite a different situation, it is a known const at compile
time value located on the stack.
> If it was just changing this one function I'd still object as it makes it differ
> from _every other test predicate_ using vma_flags_t but maybe to humour you I'd
> change it, but surely by this argument you're essentially objecting to the whole
> series?
I only think that if you are taking a heap input that is not of known
value you should continue to pass by pointer as is generally expected
in the C style we use.
And it isn't saying anything about the overall technique in the
series, just a minor note about style.
> I am not sure about this 'idiomatic kernel style' thing either, it feels rather
> conjured. Yes you wouldn't ordinarily pass something larger than a register size
> by-value, but here the intent is for it to be inlined anyway right?
Well, exactly, we don't normally pass things larger than an interger
by value, that isn't the style, so I don't think it is such a great
thing to introduce here kind of unnecessarily.
The troubles I recently had were linked to odd things like gcov and
very old still supported versions of gcc. Also I saw a power compiler
make a very strange choice to not inline something that evaluated to a
constant.
Jason
On Tue, Jan 20, 2026 at 11:22:45AM -0400, Jason Gunthorpe wrote:
> On Tue, Jan 20, 2026 at 03:10:54PM +0000, Lorenzo Stoakes wrote:
> > The natural implication of what you're saying is that we can no longer use this
> > from _anywhere_ because - hey - passing this by value is bad so now _everything_
> > has to be re-written as:
>
> No, I'm not saying that, I'm saying this specific case where you are
> making an accessor to reach an unknown value located on the heap
OK it would have been helpful for you to say that! Sometimes reviews feel
like a ratcheting series of 'what do you actually mean?'s... :)
> should be using a pointer as both a matter of style and to simplify
> life for the compiler.
OK fine.
>
> > vma_flags_t flags_to_set = mk_vma_flags(<flags>);
> >
> > if (vma_flags_test(&flags, &flags_to_set)) { ... }
>
> This is quite a different situation, it is a known const at compile
> time value located on the stack.
Well as a const time thing it'll be optimised to just a value assuming
nothing changes flags_to_set in the mean time. You'd hope.
Note that we have xxx_mask() variants, such that you can do, e.g.:
vma_flags_t flags1 = mk_vma_flags(...);
vma_flags_t flags2 = mk_vma_flags(...);
if (vma_flags_test_mask(flags1, flags2)) {
...
}
ASIDE ->
NOTE: A likely use of this, and one I already added is so we can do
e.g.:
#define VMA_REMAP_FLAGS mk_vma_flags(VMA_IO_BIT, VMA_PFNMAP_BIT, \
VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT)
...
if (vma_flagss_test_mask(flags, VMA_REMAP_FLAGS)) { ... }
Which would be effectively a const input anyway.
<- ASIDE
Or in a world where flags1 is a const pointer now:
if (vma_flags_test_mask(&flags1, flags2)) { ... }
Which makes the form... kinda weird. Then again it's consistent with other
forms which update flags1, ofc we name this separately, e.g. flags, to_test
or flags, to_set so I guess not such a problme.
Now, nobody is _likely_ to do e.g.:
if (vma_flags_test_mask(&vma1->flags, vma2->flags)) { ... }
In this situation, but they could.
However perhaps having one value pass-by-const-pointer and the other
by-value essentially documents the fact you're being dumb.
And if somebody really needs something like this (not sure why) we could
add something.
But yeah ok, I'll change this. It's more than this case it's also all the
test stuff but shouldn't be a really huge change.
>
> > If it was just changing this one function I'd still object as it makes it differ
> > from _every other test predicate_ using vma_flags_t but maybe to humour you I'd
> > change it, but surely by this argument you're essentially objecting to the whole
> > series?
>
> I only think that if you are taking a heap input that is not of known
> value you should continue to pass by pointer as is generally expected
> in the C style we use.
Ack.
>
> And it isn't saying anything about the overall technique in the
> series, just a minor note about style.
OK good, though Arnd's reply feels more like a comment on the latter,
though only really doing pass-by-value for const values (in nearly all sane
cases) should hopefully mitigate.
>
> > I am not sure about this 'idiomatic kernel style' thing either, it feels rather
> > conjured. Yes you wouldn't ordinarily pass something larger than a register size
> > by-value, but here the intent is for it to be inlined anyway right?
>
> Well, exactly, we don't normally pass things larger than an interger
> by value, that isn't the style, so I don't think it is such a great
> thing to introduce here kind of unnecessarily.
>
> The troubles I recently had were linked to odd things like gcov and
> very old still supported versions of gcc. Also I saw a power compiler
> make a very strange choice to not inline something that evaluated to a
> constant.
Right ok.
>
> Jason
Thanks, Lorenzo
© 2016 - 2026 Red Hat, Inc.