In the reordered RHS path of matchesShlZExt, the code never checked that each shift amount (0, Stride, 2×Stride, …) appears at most once. When the same shift appeared in multiple lanes, it still filled Order, producing a non-permutation (e.g. Order = [0,0,0,1]). That led to bad shuffle masks and miscompilation (e.g. shuffles with poison). The patch adds an explicit duplicate check: before setting Order[Idx] = Pos, it ensures Pos has not been seen before, using a SmallBitVector SeenPositions(VF). If a position is seen twice, the function returns false and the optimization is not applied.
60 lines
3.5 KiB
LLVM
60 lines
3.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: opt -S -passes=slp-vectorizer -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 < %s | FileCheck %s
|
|
|
|
define void @duplicate_shift_i128_store(ptr %base, i32 %spec_select, i32 %spec_select37, i1 %narrow) {
|
|
; CHECK-LABEL: define void @duplicate_shift_i128_store(
|
|
; CHECK-SAME: ptr [[BASE:%.*]], i32 [[SPEC_SELECT:%.*]], i32 [[SPEC_SELECT37:%.*]], i1 [[NARROW:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 1024
|
|
; CHECK-NEXT: [[P_INSERT_11:%.*]] = select i1 [[NARROW]], i128 158456325046975419260797452288, i128 158456325028528675187087900672
|
|
; CHECK-NEXT: [[ZEXT37:%.*]] = zext i32 [[SPEC_SELECT37]] to i128
|
|
; CHECK-NEXT: [[SHL37:%.*]] = shl nuw nsw i128 [[ZEXT37]], 32
|
|
; CHECK-NEXT: [[MASKED37:%.*]] = and i128 [[SHL37]], 18446742974197923840
|
|
; CHECK-NEXT: [[AND37_255:%.*]] = and i32 [[SPEC_SELECT37]], 255
|
|
; CHECK-NEXT: [[ZEXT37_255:%.*]] = zext nneg i32 [[AND37_255]] to i128
|
|
; CHECK-NEXT: [[SHL37_255:%.*]] = shl nuw nsw i128 [[ZEXT37_255]], 32
|
|
; CHECK-NEXT: [[P_MASK_7:%.*]] = or disjoint i128 [[P_INSERT_11]], [[MASKED37]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i128 [[P_MASK_7]], [[SHL37_255]]
|
|
; CHECK-NEXT: [[PREFIX_HIGH:%.*]] = and i32 [[SPEC_SELECT]], -16777216
|
|
; CHECK-NEXT: [[ZEXT_HIGH:%.*]] = zext i32 [[PREFIX_HIGH]] to i128
|
|
; CHECK-NEXT: [[P_MASK_0:%.*]] = or disjoint i128 [[TMP5]], [[ZEXT_HIGH]]
|
|
; CHECK-NEXT: [[AND_16711680:%.*]] = and i32 [[SPEC_SELECT]], 16711680
|
|
; CHECK-NEXT: [[ZEXT_16711680:%.*]] = zext nneg i32 [[AND_16711680]] to i128
|
|
; CHECK-NEXT: [[P_MASK_4:%.*]] = or disjoint i128 [[P_MASK_0]], [[ZEXT_16711680]]
|
|
; CHECK-NEXT: [[AND_255:%.*]] = and i32 [[SPEC_SELECT]], 255
|
|
; CHECK-NEXT: [[ZEXT_255:%.*]] = zext nneg i32 [[AND_255]] to i128
|
|
; CHECK-NEXT: [[AND_65280:%.*]] = and i32 [[SPEC_SELECT]], 65280
|
|
; CHECK-NEXT: [[ZEXT_65280:%.*]] = zext nneg i32 [[AND_65280]] to i128
|
|
; CHECK-NEXT: [[P_MASK_1:%.*]] = or disjoint i128 [[P_MASK_4]], [[ZEXT_65280]]
|
|
; CHECK-NEXT: [[P_INSERT_0:%.*]] = or disjoint i128 [[P_MASK_1]], [[ZEXT_255]]
|
|
; CHECK-NEXT: store i128 [[P_INSERT_0]], ptr [[ARRAYIDX]], align 16
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i8, ptr %base, i64 1024
|
|
%p_insert_11 = select i1 %narrow, i128 158456325046975419260797452288, i128 158456325028528675187087900672
|
|
%zext37 = zext i32 %spec_select37 to i128
|
|
%shl37 = shl nuw nsw i128 %zext37, 32
|
|
%masked37 = and i128 %shl37, 18446742974197923840
|
|
%and37_255 = and i32 %spec_select37, 255
|
|
%zext37_255 = zext nneg i32 %and37_255 to i128
|
|
%shl37_255 = shl nuw nsw i128 %zext37_255, 32
|
|
%p_mask_7 = or disjoint i128 %p_insert_11, %masked37
|
|
%p_insert_7 = or disjoint i128 %p_mask_7, %shl37_255
|
|
%prefix_high = and i32 %spec_select, -16777216
|
|
%zext_high = zext i32 %prefix_high to i128
|
|
%p_insert_6 = or disjoint i128 %p_insert_7, %zext_high
|
|
%and_16711680 = and i32 %spec_select, 16711680
|
|
%zext_16711680 = zext nneg i32 %and_16711680 to i128
|
|
%p_mask_4 = or disjoint i128 %p_insert_6, %zext_16711680
|
|
%and_255 = and i32 %spec_select, 255
|
|
%zext_255 = zext nneg i32 %and_255 to i128
|
|
%and_65280 = and i32 %spec_select, 65280
|
|
%zext_65280 = zext nneg i32 %and_65280 to i128
|
|
%p_mask_0 = or disjoint i128 %p_mask_4, %zext_65280
|
|
%p_insert_0 = or disjoint i128 %p_mask_0, %zext_255
|
|
; Generic store i128 (triggers SLP).
|
|
store i128 %p_insert_0, ptr %arrayidx, align 16
|
|
ret void
|
|
}
|