[LLVMdev] [Propose] Add address-taken bit to GlobalVariable for disambiguation purpose
Shuxin Yang
shuxin.llvm at gmail.com
Tue Oct 29 16:39:56 PDT 2013
Hi, There:
I'd like to add bit, called "addr_not_taken", to GlobalVariable in
order to
indicate if a GlobalVariable doesn't has its address taken or not.
1.The motivation
===============
The motivation can be explained by the following example. In this
example,
variable x does not have its address taken, therefore, it cannot be
indirectly
access. So, we can prove "x" and "*p" don't overlap.
-----------------
static int x;
foo(int *p) {
x = 1;
*p = 2; // do not modify x
x = x + 1;
}
---------------
The semantic of llvm::GlobalVariable::addr_not_taken is:
1). Of course, the global variable in question doesn't have its
address taken, and
2). the global variable is not volatile, and
3). Compiler need to see all the references of the variables.
The address-not-taken can be used to disambiguate memory operations
between:
o. direct load/store to a global variable which does not have its
address taken, and
o. any arbitrary indirect memory operations.
The 2) is to ensure compiler will not set a volatile variable
"addr-not-taken", even
if all its reference are direct accesses.
The 3) does not necessarily imply the global variable has internal
linkage type, see
following scenario S2 and S3.
Since llvm::GlobalVariable has plenty of vacant bits (for flags),
this bit will
not increase its size.
2. Scenarios where llvm::GlobalVariable::addr_not_taken is useful
=================================================================
NOTE: As you can see from the S2 and S3, addr_not_taken can serve as
additional info
of the input IR. In that sense, we should view "addr_not_taken" as
an attribute of
a variable (akin to GNU's function-attribute).
S1) C-thinking programs likely have lots of global variables, and most
of them
are directly referenced.
It would be more useful in LTO mode as in this mode more global
variables
will be recognized as "address-not-taken".
S2) Compiler may generate some global variables for some special
purpose or for some
special languages. These global variables are normally directly
accessed. Compiler
can mark the variable "addr-not-taken" to avoid uncessary alias.
We would otherwise
need to introduce a special meta-data for this purpose.
Go back to semantic 3). At the moment a compiler generate such
variables,
it does not physically "see" all the reference of these vars,
however it
is pretty sure how these these variable will be accessed.
Note that in this scenario, the references of these
compiler-created global
variables may occur in multiple modules. Therefore, they don't have
"internal"
linkage.
S3) Consider this snippet:
S3) Consider this snippet:
---------------------
static int xyz; // address-not-taken
foo() {
access xyz;
}
bar() { access xyz; }
----------------------
For some reasons (say, triage problematic functions), we many
separate foo()
and bar() into different source files. For this purpose, we have
to get
rid of "static" from "xyz", which may bring new problem once in a
while,
for instance, bug disappear, performance degrade.
Introducing address-not-taken will alleviate such troubles.
3. Q&A
======
Q1: If we have nice points-to analysis, do we still need what you
propose today.
--------------------------------------------------------------------------------
A1: For scenario S2 and S3, points-to analysis will not help. I agree
S2 and S3
are not very important.
For S1, sure, it does not need to be a "nice" analyzer, even a
"stupid" anlayzer
should work for this end. The problem is that points-to analyses are
normally very
expensive. They are normally invoked once the in the entire compiler
pipeline,
before that point, we cannot disambiguate global-variable and indirection
mem-ops.
On the other hand, compiler can afford re-analyzing address-taken for
particular global variable or all global variables again and again after
some optimizations (say, DCE). We certainly cannot affording to invoke
the prohibitively expensive points-to analysis for so many times.
Q2: Does addr-not-taken imply "unnamed_addr" (Nick asked this
question the other day)
-------------------------------------------------------------------------------------
A2: No. Consider S2 and S3.
For S1, I don't know for sure if variable name matter or not if
debug-info is
turned on.
Q3: Can we save the not-addr-taken to meta-data?
-------------------------------------------------
A3: Meta-data, by its very nature, is part of IR. It is pretty slow
to access.
We can view addr-not-taken as an attribute of the globalvar (just
like
function as attributes like readonly/malloc/....).
I'm aware of other compilers whose symbol-tables have imilar bits
for all kind of symbols (funcitons and data at level).
Q4: Can we save the not-addr-taken to an analysis pass
-----------------------------------------------------
A4: If we implement this way:
o. we have add a statement to most, if not all, passes to claim it
preserve this addr-taken analysis result, which is bit anonying.
o. The address-taken information collected before LTO (aka pre-IPO),
cannot be fed to LTO, unless we re-analyze them from ground up.
Q5: How difficult is it to maintain this flag
-----------------------------------------------------
A5: It is almost maintenance free, in the sense that we almost never
come across a situation when an optimizer take the address of
the globalvar which is marked addr-not-taken.
It would be nice if we can afford re-analyze addr-taken over and
over again to make sure the information is precise. However,
we don't have to do that --- while the information is imprecise,
it is conservatively correct.
Q6: Analyzing addr-taken is inexpensive. Why not just disambiguate by
analyzing addr-taken on the fly during AA phase (Nick asked the
question
other day)?
-----------------------------------------------------
A6: While analyzing addr-taken for data is more expensive
than analyzing addr-takne for funciton, I think it is still
relatively
inexpensive.
That said, I don't think it is still inexpensive if we
re-analyze the
addr-taken again and again *ON THE FLY". It is really difficult to
predict compile-time impact. You never know how many global variables
in a program, and you never know how extensive they are used.
Poorly-written program tends to have lots of global-vars.
Thanks
Shuxin
More information about the llvm-dev
mailing list