Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Jan 2018 09:25:34 -0800
From:      Conrad Meyer <cem@freebsd.org>
To:        "Rodney W. Grimes" <rgrimes@freebsd.org>
Cc:        src-committers <src-committers@freebsd.org>, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r327354 - head/sys/vm
Message-ID:  <CAG6CVpVQqyhub0g-iOjKbZYEaEqAy87WdrocoQ_MxYhvbz1k%2BQ@mail.gmail.com>
In-Reply-To: <201801191704.w0JH4rgT072967@pdx.rh.CN85.dnsmgr.net>
References:  <601ee1a2-8f4e-518d-4c86-89871cd652af@vangyzen.net> <201801191704.w0JH4rgT072967@pdx.rh.CN85.dnsmgr.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jan 19, 2018 at 9:04 AM, Rodney W. Grimes
<freebsd@pdx.rh.cn85.dnsmgr.net> wrote:
> BUT I do not believe this bit of "style" has anything to do with
> readability of code, and has more to do with how code runs on a
> processor and stack frames.   If you defer the declaration of
> "int i" in the above code does that compiler emmit code to allocate
> a new stack frame, or does it just add space to the function stack
> frame for this?
>
> What happens if you do
>         for (int i =3D 0; i < pages;) { }
>
>         for (int i =3D 1; i < pages;) { }
> as 2 seperate loops, do we allocate 2 i's on the stack at
> function startup, or do we defer and allacte each one
> only when that basic block runs, or do we allocate 1 i
> and reuse it, I know that the compiler makes functional
> code but how is that functionality done?  The current
> style leaves no doubt about how things are done from
> that perspective.

Modern (and I'm using that word very loosely here =E2=80=94 think GCC did t=
his
10+ years ago) optimizing compilers do something called liveness
tracking[0] for variables to determine the scope they are used in
(something like the region between last write and last read).  So in
that sense, optimizing compilers do not care whether you declare the
variable at function scope or local scope =E2=80=94 they always determine t=
he
local scope the variable is alive in.  (Other than for shadowing,
which we strongly discourage and is considered bad style.)

Liveness analysis is part of register allocation[1], which typically
uses a graph coloring algorithm to determine the minimal number of
distinct registers needed to hold live values.  If the number of
registers needed is more than the machine provides, some values must
be spilled to the stack.  (On modern x86 it doesn't matter too much
what you spill to the stack, because the top few words of the stack
region is actually quite fast, but clever compilers targeting other
platforms may attempt to spill less frequently accessed values.)

I think I recall Clang and other LLVM frontends do something nutty
when they emit intermediary representation, like using a new register
for each assignment.  This relies on the register allocater to reduce
that to something sane for the target machine.

Best,
Conrad

[0]: https://en.wikipedia.org/wiki/Live_variable_analysis
[1]: https://en.wikipedia.org/wiki/Register_allocation



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAG6CVpVQqyhub0g-iOjKbZYEaEqAy87WdrocoQ_MxYhvbz1k%2BQ>