Looking at the test/Analysis/MemoryDependenceAnalysis/InvariantLoad.ll
:
define i8 @test(i1 %cmp) {
entry:
%p = alloca i8
%addr = getelementptr inbounds i8, i8* %p, i64 0
store i8 5, i8* %addr
br label %header
header:
%i = phi i8 [0, %entry], [%i.inc, %backedge]
br i1 %cmp, label %alive, label %dead
dead:
call void @foo(i8* %p)
%v = load i8, i8* %addr, !invariant.load !1
%i.1 = add i8 %i, %v
br label %alive
alive:
%i.2 = phi i8 [%i, %header], [%i.1, %dead]
store i8 -5, i8* %addr
br label %backedge
backedge:
call void @llvm.memset.p0i8.i8(i8 * align 1 %p, i8 0, i32 1, i1 false)
%i.inc = add i8 %i.2, 1
%cmp.loop = icmp ugt i8 %i.inc, 100
br i1 %cmp.loop, label %exit, label %header
exit:
%res = load i8, i8* %addr
ret i8 %res
}
we have the invariant load %v = load i8, i8* %addr, !invariant.load !1
. The memory location
is initialised by store i8 5, i8* %addr
and, following the execution of the load, is modified by
store i8 -5, i8* %addr
?
Is this undefined behaviour?
The LangRef says:
If a load instruction tagged with the
!invariant.load
metadata is executed, the memory location referenced by the load has
to contain the same value at all points in the program where the
memory location is dereferenceable; otherwise, the behavior is
undefined.
Or should we interpret this to mean that the load is never executed? (The basic block label dead
suggests so, but it’s not entirely clear).
Could we optimise the load to 5
, i.e. delete it and change %i.1 = ...
into %i.1 = add i8 %i, 5
?