[LLVMdev] LLVM 2.4 problem? (resend)

Eli Friedman eli.friedman at gmail.com
Wed Oct 15 19:34:52 PDT 2008


On Wed, Oct 15, 2008 at 8:28 AM, Chris Lattner <clattner at apple.com> wrote:
>> I do think however that it's bit dangerous to combine static constants
>> across compilation units.
>
> GCC does the same things with strings in some cases.  You shouldn't
> depend on this behavior if you want portable code.

Combining is explicitly allowed for strings in C: 6.5.2.5p8: "String
literals, and compound literals with const-qualified types, need not
designate distinct objects."  This isn't allowed for distinct
declarations.

6.5.9p6: "Two pointers compare equal if and only if both are null
pointers, both are pointers to the same object (including a pointer to
an object and a subobject at its beginning) or function, both are
pointers to one past the last element of the same array object, or one
is a pointer to one past the end of one array object and the other is
a pointer to the start of a different array object that happens to
immediately follow the first array object in the address space."

6.2.4: "An object exists, has a constant address, and retains its
last-stored value throughout its lifetime."

6.7: "A definition of an identifier is a declaration for that
identifier that: — for an object, causes storage to be reserved for
that object;"

There isn't any other reasonable interpretation of the standard.

Also, the only semantics that "const" has in C is that writing to an
object with a const-qualified type is illegal.

> If you avoid
> marking the global variable const, you should have better luck.

Not marking the variable const only makes the problem more obscure.
Testcase in C:

static char x = 1, y = 1;int c() {char* u = &x; char* v = &y; return u
== v;} int d() {return x+y;}

Running this through "llvm-gcc -O0 -emit-llvm -c -x c - -o - | opt
-mem2reg -globalopt -constmerge -instcombine" has precisely the same
effect: c returns 1.

It's conceivable that globalopt+constmerge could do even crazier
stuff. Potential example: suppose we have two mallocs, and store the
allocated pointers into globals.   GlobalOpt knows how to turn mallocs
into statically allocated globals.  Then suppose there's exactly one
store to each of these mallocs: GlobalOpt knows how to turn these into
constant globals.  Then, ConstMerge or the AsmPrinter will actually
merge them, so the computed address ends up being the same.
Therefore, we conclude that malloc(1) == malloc(1) can be true in some
situations!  Now, this doesn't actually work because malloc
elimination transformation isn't quite aggressive enough, but making
this work wouldn't require any controversial changes.

This bug actually manifests itself in two places: one is
ConstantMerge, the other is the AsmPrinter.  It's non-trivial to fix
because it's really a design bug: we assume that constant==mergeable,
which simply isn't true.  There are a few different ways of fixing
this; however, I think the only real option is to add a new
"mergeable" linkage type.

-Eli




More information about the llvm-dev mailing list