Skip to content

Commit

Permalink
[WebAssembly] Mark @llvm.wasm.shuffle lane indices as immediates
Browse files Browse the repository at this point in the history
This intrinsic is meant to lower directly to the i8x16.shuffle instruction,
which takes its lane index arguments as immmediates. The ISel for the intrinsic
assumed that the lane index arguments were constants, so bitcode that
"incorrectly" used this intrinsic with non-immediate arguments caused an
assertion failure in the backend.

Avoid the crash by defining the lane index arguments to be immediates, matching
the underlying instruction. Update ISel accordingly. This change means that the
bitcode that previously caused a crash will now fail to validate.

Fixes #55559.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D149898
  • Loading branch information
tlively committed May 5, 2023
1 parent aea866c commit 72a7231
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 18 deletions.
10 changes: 9 additions & 1 deletion llvm/include/llvm/IR/IntrinsicsWebAssembly.td
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,15 @@ def int_wasm_shuffle :
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;
[IntrNoMem, IntrSpeculatable,
ImmArg<ArgIndex<2>>, ImmArg<ArgIndex<3>>,
ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<5>>,
ImmArg<ArgIndex<6>>, ImmArg<ArgIndex<7>>,
ImmArg<ArgIndex<8>>, ImmArg<ArgIndex<9>>,
ImmArg<ArgIndex<10>>, ImmArg<ArgIndex<11>>,
ImmArg<ArgIndex<12>>, ImmArg<ArgIndex<13>>,
ImmArg<ArgIndex<14>>, ImmArg<ArgIndex<15>>,
ImmArg<ArgIndex<16>>, ImmArg<ArgIndex<17>>]>;
def int_wasm_sub_sat_signed :
DefaultAttrsIntrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>],
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1823,7 +1823,8 @@ SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
const SDValue &MaskIdx = Op.getOperand(OpIdx + 1);
if (MaskIdx.isUndef() ||
cast<ConstantSDNode>(MaskIdx.getNode())->getZExtValue() >= 32) {
Ops[OpIdx++] = DAG.getConstant(0, DL, MVT::i32);
bool isTarget = MaskIdx.getNode()->getOpcode() == ISD::TargetConstant;
Ops[OpIdx++] = DAG.getConstant(0, DL, MVT::i32, isTarget);
} else {
Ops[OpIdx++] = MaskIdx;
}
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,22 @@ defm SHUFFLE :
def wasm_shuffle_t : SDTypeProfile<1, 18, []>;
def wasm_shuffle : SDNode<"WebAssemblyISD::SHUFFLE", wasm_shuffle_t>;
foreach vec = AllVecs in {
// The @llvm.wasm.shuffle intrinsic has immediate arguments that become TargetConstants.
def : Pat<(vec.vt (wasm_shuffle (vec.vt V128:$x), (vec.vt V128:$y),
(i32 timm:$m0), (i32 timm:$m1),
(i32 timm:$m2), (i32 timm:$m3),
(i32 timm:$m4), (i32 timm:$m5),
(i32 timm:$m6), (i32 timm:$m7),
(i32 timm:$m8), (i32 timm:$m9),
(i32 timm:$mA), (i32 timm:$mB),
(i32 timm:$mC), (i32 timm:$mD),
(i32 timm:$mE), (i32 timm:$mF))),
(SHUFFLE $x, $y,
imm:$m0, imm:$m1, imm:$m2, imm:$m3,
imm:$m4, imm:$m5, imm:$m6, imm:$m7,
imm:$m8, imm:$m9, imm:$mA, imm:$mB,
imm:$mC, imm:$mD, imm:$mE, imm:$mF)>;
// Normal shufflevector instructions may have normal constant arguemnts.
def : Pat<(vec.vt (wasm_shuffle (vec.vt V128:$x), (vec.vt V128:$y),
(i32 LaneIdx32:$m0), (i32 LaneIdx32:$m1),
(i32 LaneIdx32:$m2), (i32 LaneIdx32:$m3),
Expand Down
19 changes: 3 additions & 16 deletions llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -157,29 +157,16 @@ define <16 x i8> @narrow_unsigned_v16i8(<8 x i16> %low, <8 x i16> %high) {
; CHECK-SAME: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0{{$}}
; CHECK-NEXT: return $pop[[R]]{{$}}
declare <16 x i8> @llvm.wasm.shuffle(
<16 x i8>, <16 x i8>, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,
i32, i32, i32, i32, i32)
<16 x i8>, <16 x i8>, i32 immarg, i32 immarg, i32 immarg, i32 immarg,
i32 immarg, i32 immarg, i32 immarg, i32 immarg, i32 immarg, i32 immarg,
i32 immarg, i32 immarg, i32 immarg, i32 immarg, i32 immarg, i32 immarg)
define <16 x i8> @shuffle_v16i8(<16 x i8> %x, <16 x i8> %y) {
%res = call <16 x i8> @llvm.wasm.shuffle(<16 x i8> %x, <16 x i8> %y,
i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7,
i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 35)
ret <16 x i8> %res
}

; CHECK-LABEL: shuffle_undef_v16i8:
; NO-CHECK-NOT: i8x16
; CHECK-NEXT: .functype shuffle_undef_v16i8 (v128, v128) -> (v128){{$}}
; CHECK-NEXT: i8x16.shuffle $push[[R:[0-9]+]]=, $0, $1,
; CHECK-SAME: 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2{{$}}
; CHECK-NEXT: return $pop[[R]]{{$}}
define <16 x i8> @shuffle_undef_v16i8(<16 x i8> %x, <16 x i8> %y) {
%res = call <16 x i8> @llvm.wasm.shuffle(<16 x i8> %x, <16 x i8> %y,
i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef,
i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef,
i32 undef, i32 undef, i32 undef, i32 2)
ret <16 x i8> %res
}

; CHECK-LABEL: laneselect_v16i8:
; CHECK-NEXT: .functype laneselect_v16i8 (v128, v128, v128) -> (v128){{$}}
; CHECK-NEXT: i8x16.relaxed_laneselect $push[[R:[0-9]+]]=, $0, $1, $2{{$}}
Expand Down

0 comments on commit 72a7231

Please sign in to comment.