-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Description
llvm commit: 15a192c
Reproduce with:
opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=separate-const-offset-from-gep -S separate-offset-from-gep-trunc-miscompile.ll
The attached code:
define ptr @src(ptr %p, i64 %a) {
%add = add i64 %a, 8
%trunc = trunc i64 %add to i32
%sext = sext i32 %trunc to i64
%arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %sext
ret ptr %arrayidx
}
is wrongly transformed into this code:
define ptr @src(ptr %p, i64 %a) #0 {
%1 = trunc i64 %a to i32
%2 = sext i32 %1 to i64
%3 = getelementptr i32, ptr %p, i64 %2
%arrayidx2 = getelementptr i8, ptr %3, i64 32
ret ptr %arrayidx2
}
Alive2 shows this transformation to be illegal: alive2 link.
Observations
This might be related to the (to me) unexpected handling of the NonNegative
flag in ConstantOffsetExtractor::find
:
It isn't cleared for trunc, but it is for zext "because zext(a) >= 0 does not imply a >= 0" -- that doesn't hold for trunc either.
The meaning of NonNegative
also seems odd: the documentation, says
NonNegative -- Whether V is guaranteed to be non-negative. For example, an index of an inbounds GEP is guaranteed to be non-negative. Levaraging this, we can better split inbounds GEPs.
I don't think that's right, inbounds GEP indices can be negative.
The unchanged passing of SignExtended
and ZeroExtended
for trunc might also be worth checking in this context.
Found while looking into #154116.