diff options
| author | Thomas Lively <tlively@google.com> | 2018-09-07 21:54:46 +0000 |
|---|---|---|
| committer | Thomas Lively <tlively@google.com> | 2018-09-07 21:54:46 +0000 |
| commit | a0d25815a063bc825d0962dfd93e225242599795 (patch) | |
| tree | cea4a07bfd972b9f9f7fd4c756f82dbe099260b8 /llvm/lib/Target/WebAssembly | |
| parent | 3a406e5a744b836b1e170a3c7f9cff4893b5d3f1 (diff) | |
| download | bcm5719-llvm-a0d25815a063bc825d0962dfd93e225242599795.tar.gz bcm5719-llvm-a0d25815a063bc825d0962dfd93e225242599795.zip | |
[WebAssembly] v8x16.shuffle
Summary:
Since the shuffle mask is not exposed as an operand in the native ISel
DAG, create a new WebAssembly ISD node exposing the mask. The mask is
lowered as sixteen immediate byte indices no matter what type the
original vector shuffle was operating on.
This CL depends on D51656
Reviewers: aheejin, dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D51659
llvm-svn: 341718
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
4 files changed, 95 insertions, 0 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def index c12550feabb..3c44d04598c 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def @@ -21,5 +21,6 @@ HANDLE_NODETYPE(ARGUMENT) HANDLE_NODETYPE(Wrapper) HANDLE_NODETYPE(BR_IF) HANDLE_NODETYPE(BR_TABLE) +HANDLE_NODETYPE(SHUFFLE) // add memory opcodes starting at ISD::FIRST_TARGET_MEMORY_OPCODE here... diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index b3775ce4ff6..74064af40b9 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -126,6 +126,17 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( // There is no i64x2.mul instruction setOperationAction(ISD::MUL, MVT::v2i64, Expand); + // We have custom shuffle lowering to expose the shuffle mask + if (Subtarget->hasSIMD128()) { + for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32}) { + setOperationAction(ISD::VECTOR_SHUFFLE, T, Custom); + } + if (EnableUnimplementedWasmSIMDInstrs) { + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2i64, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2f64, Custom); + } + } + // As a special case, these operators use the type to mean the type to // sign-extend from. setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); @@ -804,6 +815,8 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op, return LowerCopyToReg(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); + case ISD::VECTOR_SHUFFLE: + return LowerVECTOR_SHUFFLE(Op, DAG); } } @@ -953,6 +966,32 @@ WebAssemblyTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, } } +SDValue +WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask(); + MVT VecType = Op.getOperand(0).getSimpleValueType(); + assert(VecType.is128BitVector() && "Unexpected shuffle vector type"); + size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8; + + // Space for two vector args and sixteen mask indices + SDValue Ops[18]; + size_t OpIdx = 0; + Ops[OpIdx++] = Op.getOperand(0); + Ops[OpIdx++] = Op.getOperand(1); + + // Expand mask indices to byte indices and materialize them as operands + for (size_t I = 0, Lanes = Mask.size(); I < Lanes; ++I) { + for (size_t J = 0; J < LaneBytes; ++J) { + Ops[OpIdx++] = + DAG.getConstant((uint64_t)Mask[I] * LaneBytes + J, DL, MVT::i32); + } + } + + return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, MVT::v16i8, Ops); +} + //===----------------------------------------------------------------------===// // WebAssembly Optimization Hooks //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h index 7955876716e..7b22651ff6d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -98,6 +98,7 @@ private: SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; SDValue LowerCopyToReg(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; }; namespace WebAssembly { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index 96c2ad54af5..5022ea5dea0 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -218,6 +218,36 @@ defm "" : Splat<v2i64, "i64x2", I64, splat2, 6>; defm "" : Splat<v4f32, "f32x4", F32, splat4, 7>; defm "" : Splat<v2f64, "f64x2", F64, splat2, 8>; +defm SHUFFLE_v16i8 : + SIMD_I<(outs V128:$dst), + (ins V128:$x, V128:$y, + vec_i8imm_op:$m0, vec_i8imm_op:$m1, + vec_i8imm_op:$m2, vec_i8imm_op:$m3, + vec_i8imm_op:$m4, vec_i8imm_op:$m5, + vec_i8imm_op:$m6, vec_i8imm_op:$m7, + vec_i8imm_op:$m8, vec_i8imm_op:$m9, + vec_i8imm_op:$mA, vec_i8imm_op:$mB, + vec_i8imm_op:$mC, vec_i8imm_op:$mD, + vec_i8imm_op:$mE, vec_i8imm_op:$mF), + (outs), + (ins + vec_i8imm_op:$m0, vec_i8imm_op:$m1, + vec_i8imm_op:$m2, vec_i8imm_op:$m3, + vec_i8imm_op:$m4, vec_i8imm_op:$m5, + vec_i8imm_op:$m6, vec_i8imm_op:$m7, + vec_i8imm_op:$m8, vec_i8imm_op:$m9, + vec_i8imm_op:$mA, vec_i8imm_op:$mB, + vec_i8imm_op:$mC, vec_i8imm_op:$mD, + vec_i8imm_op:$mE, vec_i8imm_op:$mF), + [], + "v8x16.shuffle\t$dst, $x, $y, "# + "$m0, $m1, $m2, $m3, $m4, $m5, $m6, $m7, "# + "$m8, $m9, $mA, $mB, $mC, $mD, $mE, $mF", + "v8x16.shuffle\t"# + "$m0, $m1, $m2, $m3, $m4, $m5, $m6, $m7, "# + "$m8, $m9, $mA, $mB, $mC, $mD, $mE, $mF", + 23>; + let isCommutable = 1 in { defm ADD : SIMDBinaryInt<add, "add", 24>; defm ADD : SIMDBinaryFP<fadd, "add", 122>; @@ -282,6 +312,30 @@ foreach t2 = !foldl( ) in def : Pat<(t1 (bitconvert (t2 V128:$v))), (t1 V128:$v)>; +// Shuffles after custom lowering +def wasm_shuffle_t : SDTypeProfile<1, 18, []>; +def wasm_shuffle : SDNode<"WebAssemblyISD::SHUFFLE", wasm_shuffle_t>; +foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in { +def : Pat<(v16i8 (wasm_shuffle (vec_t V128:$x), (vec_t V128:$y), + (i32 LaneIdx32:$m0), (i32 LaneIdx32:$m1), + (i32 LaneIdx32:$m2), (i32 LaneIdx32:$m3), + (i32 LaneIdx32:$m4), (i32 LaneIdx32:$m5), + (i32 LaneIdx32:$m6), (i32 LaneIdx32:$m7), + (i32 LaneIdx32:$m8), (i32 LaneIdx32:$m9), + (i32 LaneIdx32:$mA), (i32 LaneIdx32:$mB), + (i32 LaneIdx32:$mC), (i32 LaneIdx32:$mD), + (i32 LaneIdx32:$mE), (i32 LaneIdx32:$mF))), + (v16i8 (SHUFFLE_v16i8 (vec_t V128:$x), (vec_t V128:$y), + (i32 LaneIdx32:$m0), (i32 LaneIdx32:$m1), + (i32 LaneIdx32:$m2), (i32 LaneIdx32:$m3), + (i32 LaneIdx32:$m4), (i32 LaneIdx32:$m5), + (i32 LaneIdx32:$m6), (i32 LaneIdx32:$m7), + (i32 LaneIdx32:$m8), (i32 LaneIdx32:$m9), + (i32 LaneIdx32:$mA), (i32 LaneIdx32:$mB), + (i32 LaneIdx32:$mC), (i32 LaneIdx32:$mD), + (i32 LaneIdx32:$mE), (i32 LaneIdx32:$mF)))>; +} + // arbitrary other BUILD_VECTOR patterns def : Pat<(v16i8 (build_vector (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), |

