Description
This C code snippet:
void foo() {
static int baz = 42;
int *p, *q = p;
printf("%p %p\n", p, q);
p = &baz;
q = p;
}
is transformed into
define void @foo() {
entry:
; vvvvvvvv vvvvvvvv
%call = call i32 (ptr, ...) @printf(ptr @.str, ptr @foo.baz, ptr @foo.baz)
ret void
}
by mem2reg. But if the last two lines are removed, the transformation result is:
define void @foo() {
entry:
; vvvvv vvvvv
%call = call i32 (ptr, ...) @printf(ptr @.str, ptr undef, ptr undef)
ret void
}
My environment:
- WSL2, Arch Linux
- clang 15.0.7
- tried
-O0
,-O1
,-O2
,-O3
, and-Ofast
Cause
// In file: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
static bool rewriteSingleStoreAlloca(...) {
StoreInst *OnlyStore = Info.OnlyStore;
bool StoringGlobalVal = !isa<Instruction>(OnlyStore->getOperand(0)); // true
...
for (...) {
...
if (!StoringGlobalVal) { // skipped
My Question
Although using uninitialized local variables is UB (per C11 Annex J.2), I wonder if it makes more sense not to replace load’s before any store with the stored value when handling global (static) variables?