[llvm-dev] Different index types in GEPs -> non-aliasing?
Mikael HolmÃ©n via llvm-dev
llvm-dev at lists.llvm.org
Mon Apr 18 02:00:17 PDT 2016
Hi,
It seems that opt thinks that the two pointers
%_tmp2 = getelementptr [3 x i16], [3 x i16]* %a, i16 0, i64 1
and
%_tmp4 = getelementptr [3 x i16], [3 x i16]* %a, i16 0, i16 1
does not alias? Is this intended or a bug?
Details below:
--------------
I found this when I ran opt on:
define i16 @f () {
%a = alloca [3 x i16]
; Write 98 at index 1 in the array.
; NB: using i64 as type of the index argument!
%_tmp2 = getelementptr [3 x i16], [3 x i16]* %a, i16 0, i64 1
store i16 98, i16* %_tmp2
; Read at index 1 in the array
; NB: using i16 as type of the index argument!
%_tmp4 = getelementptr [3 x i16], [3 x i16]* %a, i16 0, i16 1
%_tmp5 = load i16, i16* %_tmp4
; Check read value. If not 98, jump to bb1
%_tmp6 = icmp ne i16 %_tmp5, 98
br i1 %_tmp6, label %bb1, label %bb2
bb1:
; Error
ret i16 1;
bb2:
; Ok
ret i16 0;
}
opt -S -gvn foo.ll
and I got the result
; ModuleID = 'foo.ll'
define i16 @f() {
%a = alloca [3 x i16]
%_tmp2 = getelementptr [3 x i16], [3 x i16]* %a, i16 0, i64 1
store i16 98, i16* %_tmp2
%_tmp4 = getelementptr [3 x i16], [3 x i16]* %a, i16 0, i16 1
br i1 undef, label %bb1, label %bb2
bb1: ; preds = %0
ret i16 1
bb2: ; preds = %0
ret i16 0
}
Note the "undef" in the branch which GVN put there:
GVN iteration: 0
GVN removed: %_tmp5 = load i16, i16* %_tmp4
GVN removed: %_tmp6 = icmp ne i16 undef, 98
When digging into why GVN does this, I found this little piece of code
in GVN::AnalyzeLoadAvailability that triggers
// Loading the allocation -> undef.
if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst, TLI) ||
// Loading immediately after lifetime begin -> undef.
isLifetimeStart(DepInst)) {
Res = AvailableValue::get(UndefValue::get(LI->getType()));
return true;
}
And the DepInst here is
%a = alloca [3 x i16]
and not the store
store i16 98, i16* %_tmp2
Digging further it seems the reason for this is that the alias analysis
considers the two pointers used to store and load the value 98 are
non-aliasing, even if both the pointer and the indices has the same
values. The only difference is the type of the last value.
In e.g. BasicAliasAnalysis.cpp we have
bool BasicAAResult::isValueEqualInPotentialCycles(const Value *V,
const Value *V2) {
if (V != V2)
return false;
and in
aliasSameBasePointerGEPs:
// If the last (struct) indices are constants and are equal, the
other indices
// might be also be dynamically equal, so the GEPs can alias.
if (C1 && C2 && C1 == C2)
return MayAlias;
so here we consider two pointers to be completely different just because
the types of the last indices differ.
So is this intended or is it a bug?
What I found in the documentation of GEP is:
"When indexing into an array, pointer or vector, integers of any width
are allowed, and they are not required to be constant. These integers
are treated as signed values where relevant."
Regards,
Mikael
More information about the llvm-dev
mailing list