This is an archive of the discontinued LLVM Phabricator instance.

[GVN] Use vector ops when doing loadCoercion on a vector value
Needs ReviewPublic

Authored by ManuelJBrito on Jun 30 2023, 8:58 AM.

Details

Summary

Currently bitmasking is used for loadCoercion of vector values, this is troublesome because these operations propagate poison.
This patch uses a combination of vector operations instead.
Fixes PR63059.

Diff Detail

Event Timeline

ManuelJBrito created this revision.Jun 30 2023, 8:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 30 2023, 8:58 AM
ManuelJBrito requested review of this revision.Jun 30 2023, 8:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 30 2023, 8:58 AM
foad added inline comments.Jul 1 2023, 4:01 AM
llvm/lib/Transforms/Utils/VNCoercion.cpp
316

Do you also need to do this for the vector-of-pointers case that is handled above?

ManuelJBrito added inline comments.Jul 1 2023, 10:05 AM
llvm/lib/Transforms/Utils/VNCoercion.cpp
316

Yes, the vector-of-pointers should be converted to a vector-of-ints and then the rest of the logic would work fine for that case.
The problem is that AFAICT we can't just bitcast it to a vector-of-ints of the correct size.

Handle vector-of-ptrs.

Adding Guozhi Wei as a reviewer.

nikic added a comment.Aug 17 2023, 7:59 AM

This causes an assertion failure:

define i11 @test(ptr %loc, <4 x i6> %v) {
  store <4 x i6> %v, ptr  %loc
  %ref = load i11, ptr %loc
  ret i11 %ref
}

Update : fill mask with poison mask elem in shufflevector

nikic added a comment.Aug 28 2023, 7:49 AM

It looks like your last update dropped the vector of pointer tests?

nikic added inline comments.Aug 28 2023, 8:09 AM
llvm/lib/Transforms/Utils/VNCoercion.cpp
321

Invert condition and early return?

377

This looks incorrect to me for the case where the division isn't exact, e.g. this is a miscompile:

define i16 @test(ptr %loc, <4 x i16> %v) {
; CHECK-LABEL: define i16 @test
; CHECK-SAME: (ptr [[LOC:%.*]], <4 x i16> [[V:%.*]]) {
; CHECK-NEXT:    store <4 x i16> [[V]], ptr [[LOC]], align 8
; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[LOC]], i64 1
; CHECK-NEXT:    [[TMP1:%.*]] = extractelement <4 x i16> [[V]], i64 0
; CHECK-NEXT:    ret i16 [[TMP1]]
;
  store <4 x i16> %v, ptr %loc
  %gep = getelementptr i8, ptr %loc, i64 1
  %ref = load i16, ptr %gep
  ret i16 %ref
}

The loaded value is the high part of elements zero and the low part of element 1, not just element 0.

ManuelJBrito added inline comments.Aug 28 2023, 9:49 AM
llvm/lib/Transforms/Utils/VNCoercion.cpp
377

Nice catch! Thank you! NumEltsRequiredFromVec needs to take into consideration the offset. I'll try to support this case without making this even more complex.