diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 00e37a4af296..c491678aaaaa 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -44,6 +44,8 @@ using namespace PatternMatch; #define DEBUG_TYPE "wasm-fastisel" +extern cl::opt EnableUnimplementedWasmSIMDInstrs; + namespace { class WebAssemblyFastISel final : public FastISel { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp index fdf3a30a5c0e..bfef765c2786 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp @@ -25,6 +25,8 @@ using namespace llvm; #define DEBUG_TYPE "wasm-isel" +extern cl::opt EnableUnimplementedWasmSIMDInstrs; + //===--------------------------------------------------------------------===// /// WebAssembly-specific code to select WebAssembly machine instructions for /// SelectionDAG operations. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index a0382157f769..50b2969e2525 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -224,6 +224,12 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( } } + // Expand additional SIMD ops that V8 hasn't implemented yet + if (Subtarget->hasSIMD128() && !EnableUnimplementedWasmSIMDInstrs) { + setOperationAction(ISD::FSQRT, MVT::v4f32, Expand); + setOperationAction(ISD::FDIV, MVT::v4f32, Expand); + } + // Custom lower lane accesses to expand out variable indices if (Subtarget->hasSIMD128()) { for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32}) { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index 085c5a77e68a..953dd05fda51 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -20,6 +20,7 @@ def HasAddr32 : Predicate<"!Subtarget->hasAddr64()">; def HasAddr64 : Predicate<"Subtarget->hasAddr64()">; def HasSIMD128 : Predicate<"Subtarget->hasSIMD128()">, AssemblerPredicate<"FeatureSIMD128", "simd128">; +def HasUnimplementedSIMD : Predicate<"EnableUnimplementedWasmSIMDInstrs">; def HasAtomics : Predicate<"Subtarget->hasAtomics()">, AssemblerPredicate<"FeatureAtomics", "atomics">; def HasNontrappingFPToInt : diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index 7ac2d15c2951..08d6a5a6c83e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -94,7 +94,8 @@ def : StorePatExternSymOffOnly("STORE_"#vec_t)>; // Constant: v128.const multiclass ConstVec { - let isMoveImm = 1, isReMaterializable = 1 in + let isMoveImm = 1, isReMaterializable = 1, + Predicates = [HasSIMD128, HasUnimplementedSIMD] in defm CONST_V128_#vec_t : SIMD_I<(outs V128:$dst), ops, (outs), ops, [(set V128:$dst, (vec_t pat))], "v128.const\t$dst, "#args, @@ -276,17 +277,19 @@ multiclass ExtractLaneExtended baseInst> { } defm "" : ExtractLaneExtended<"_s", 5>; +let Predicates = [HasSIMD128, HasUnimplementedSIMD] in defm "" : ExtractLaneExtended<"_u", 6>; defm "" : ExtractLane; defm "" : ExtractLane; defm "" : ExtractLane; defm "" : ExtractLane; -// Follow convention of making implicit expansions unsigned +// It would be more conventional to use unsigned extracts, but v8 +// doesn't implement them yet def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))), - (EXTRACT_LANE_v16i8_u V128:$vec, (i32 LaneIdx16:$idx))>; + (EXTRACT_LANE_v16i8_s V128:$vec, (i32 LaneIdx16:$idx))>; def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))), - (EXTRACT_LANE_v8i16_u V128:$vec, (i32 LaneIdx8:$idx))>; + (EXTRACT_LANE_v8i16_s V128:$vec, (i32 LaneIdx8:$idx))>; // Lower undef lane indices to zero def : Pat<(and (i32 (vector_extract (v16i8 V128:$vec), undef)), (i32 0xff)), @@ -725,6 +728,7 @@ defm ABS : SIMDUnaryFP; defm NEG : SIMDUnaryFP; // Square root: sqrt +let Predicates = [HasSIMD128, HasUnimplementedSIMD] in defm SQRT : SIMDUnaryFP; //===----------------------------------------------------------------------===// @@ -748,6 +752,7 @@ let isCommutable = 1 in defm MUL : SIMDBinaryFP; // Division: div +let Predicates = [HasSIMD128, HasUnimplementedSIMD] in defm DIV : SIMDBinaryFP; // NaN-propagating minimum: min diff --git a/llvm/test/CodeGen/WebAssembly/simd-arith.ll b/llvm/test/CodeGen/WebAssembly/simd-arith.ll index 6d3d04c9e494..619b9aff1691 100644 --- a/llvm/test/CodeGen/WebAssembly/simd-arith.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-arith.ll @@ -89,12 +89,12 @@ define <16 x i8> @shl_const_v16i8(<16 x i8> %v) { ; CHECK-LABEL: shl_vec_v16i8: ; NO-SIMD128-NOT: i8x16 ; SIMD128-NEXT: .functype shl_vec_v16i8 (v128, v128) -> (v128){{$}} -; SIMD128-NEXT: i8x16.extract_lane_u $push[[L0:[0-9]+]]=, $0, 0{{$}} +; SIMD128-NEXT: i8x16.extract_lane_s $push[[L0:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: i8x16.extract_lane_u $push[[L1:[0-9]+]]=, $1, 0{{$}} ; SIMD128-NEXT: i32.shl $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; SIMD128-NEXT: i8x16.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; Skip 14 lanes -; SIMD128: i8x16.extract_lane_u $push[[L4:[0-9]+]]=, $0, 15{{$}} +; SIMD128: i8x16.extract_lane_s $push[[L4:[0-9]+]]=, $0, 15{{$}} ; SIMD128-NEXT: i8x16.extract_lane_u $push[[L5:[0-9]+]]=, $1, 15{{$}} ; SIMD128-NEXT: i32.shl $push[[L6:[0-9]+]]=, $pop[[L4]], $pop[[L5]]{{$}} ; SIMD128-NEXT: i8x16.replace_lane $push[[R:[0-9]+]]=, $pop[[L7:[0-9]+]], 15, $pop[[L6]]{{$}} @@ -121,7 +121,7 @@ define <16 x i8> @shr_s_v16i8(<16 x i8> %v, i8 %x) { ; CHECK-LABEL: shr_s_vec_v16i8: ; NO-SIMD128-NOT: i8x16 ; SIMD128-NEXT: .functype shr_s_vec_v16i8 (v128, v128) -> (v128){{$}} -; SIMD128-NEXT: i8x16.extract_lane_u $push[[L0:[0-9]+]]=, $0, 0{{$}} +; SIMD128-NEXT: i8x16.extract_lane_s $push[[L0:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: i32.const $push[[L1:[0-9]+]]=, 24{{$}} ; SIMD128-NEXT: i32.shl $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; SIMD128-NEXT: i32.const $push[[L3:[0-9]+]]=, 24{{$}} @@ -130,7 +130,7 @@ define <16 x i8> @shr_s_v16i8(<16 x i8> %v, i8 %x) { ; SIMD128-NEXT: i32.shr_s $push[[L6:[0-9]+]]=, $pop[[L4]], $pop[[L5]]{{$}} ; SIMD128-NEXT: i8x16.splat $push[[L7:[0-9]+]]=, $pop[[L6]]{{$}} ; Skip 14 lanes -; SIMD128: i8x16.extract_lane_u $push[[L7:[0-9]+]]=, $0, 15{{$}} +; SIMD128: i8x16.extract_lane_s $push[[L7:[0-9]+]]=, $0, 15{{$}} ; SIMD128-NEXT: i32.const $push[[L8:[0-9]+]]=, 24{{$}} ; SIMD128-NEXT: i32.shl $push[[L9:[0-9]+]]=, $pop[[L7]], $pop[[L8]]{{$}} ; SIMD128-NEXT: i32.const $push[[L10:[0-9]+]]=, 24{{$}} @@ -311,12 +311,12 @@ define <8 x i16> @shl_const_v8i16(<8 x i16> %v) { ; CHECK-LABEL: shl_vec_v8i16: ; NO-SIMD128-NOT: i16x8 ; SIMD128-NEXT: .functype shl_vec_v8i16 (v128, v128) -> (v128){{$}} -; SIMD128-NEXT: i16x8.extract_lane_u $push[[L0:[0-9]+]]=, $0, 0{{$}} +; SIMD128-NEXT: i16x8.extract_lane_s $push[[L0:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: i16x8.extract_lane_u $push[[L1:[0-9]+]]=, $1, 0{{$}} ; SIMD128-NEXT: i32.shl $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; SIMD128-NEXT: i16x8.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; Skip 6 lanes -; SIMD128: i16x8.extract_lane_u $push[[L4:[0-9]+]]=, $0, 7{{$}} +; SIMD128: i16x8.extract_lane_s $push[[L4:[0-9]+]]=, $0, 7{{$}} ; SIMD128-NEXT: i16x8.extract_lane_u $push[[L5:[0-9]+]]=, $1, 7{{$}} ; SIMD128-NEXT: i32.shl $push[[L6:[0-9]+]]=, $pop[[L4]], $pop[[L5]]{{$}} ; SIMD128-NEXT: i16x8.replace_lane $push[[R:[0-9]+]]=, $pop[[L7:[0-9]+]], 7, $pop[[L6]]{{$}} @@ -342,7 +342,7 @@ define <8 x i16> @shr_s_v8i16(<8 x i16> %v, i16 %x) { ; CHECK-LABEL: shr_s_vec_v8i16: ; NO-SIMD128-NOT: i16x8 ; SIMD128-NEXT: .functype shr_s_vec_v8i16 (v128, v128) -> (v128){{$}} -; SIMD128-NEXT: i16x8.extract_lane_u $push[[L0:[0-9]+]]=, $0, 0{{$}} +; SIMD128-NEXT: i16x8.extract_lane_s $push[[L0:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: i32.const $push[[L1:[0-9]+]]=, 16{{$}} ; SIMD128-NEXT: i32.shl $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; SIMD128-NEXT: i32.const $push[[L3:[0-9]+]]=, 16{{$}} @@ -351,7 +351,7 @@ define <8 x i16> @shr_s_v8i16(<8 x i16> %v, i16 %x) { ; SIMD128-NEXT: i32.shr_s $push[[L6:[0-9]+]]=, $pop[[L4]], $pop[[L5]]{{$}} ; SIMD128-NEXT: i16x8.splat $push[[L7:[0-9]+]]=, $pop[[L6]]{{$}} ; Skip 6 lanes -; SIMD128: i16x8.extract_lane_u $push[[L7:[0-9]+]]=, $0, 7{{$}} +; SIMD128: i16x8.extract_lane_s $push[[L7:[0-9]+]]=, $0, 7{{$}} ; SIMD128-NEXT: i32.const $push[[L8:[0-9]+]]=, 16{{$}} ; SIMD128-NEXT: i32.shl $push[[L9:[0-9]+]]=, $pop[[L7]], $pop[[L8]]{{$}} ; SIMD128-NEXT: i32.const $push[[L10:[0-9]+]]=, 16{{$}} @@ -1087,6 +1087,7 @@ define <4 x float> @sub_v4f32(<4 x float> %x, <4 x float> %y) { ; CHECK-LABEL: div_v4f32: ; NO-SIMD128-NOT: f32x4 +; SIMD128-VM-NOT: f32x4.div ; SIMD128-NEXT: .functype div_v4f32 (v128, v128) -> (v128){{$}} ; SIMD128-NEXT: f32x4.div $push[[R:[0-9]+]]=, $0, $1{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} @@ -1107,6 +1108,7 @@ define <4 x float> @mul_v4f32(<4 x float> %x, <4 x float> %y) { ; CHECK-LABEL: sqrt_v4f32: ; NO-SIMD128-NOT: f32x4 +; SIMD128-VM-NOT: f32x4.sqrt ; SIMD128-NEXT: .functype sqrt_v4f32 (v128) -> (v128){{$}} ; SIMD128-NEXT: f32x4.sqrt $push[[R:[0-9]+]]=, $0{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} diff --git a/llvm/test/CodeGen/WebAssembly/simd.ll b/llvm/test/CodeGen/WebAssembly/simd.ll index 29b51f16694b..3a20cb3d3e94 100644 --- a/llvm/test/CodeGen/WebAssembly/simd.ll +++ b/llvm/test/CodeGen/WebAssembly/simd.ll @@ -12,6 +12,7 @@ target triple = "wasm32-unknown-unknown" ; ============================================================================== ; CHECK-LABEL: const_v16i8: ; NO-SIMD128-NOT: i8x16 +; SIMD128-VM-NOT: v128.const ; SIMD128-NEXT: .functype const_v16i8 () -> (v128){{$}} ; SIMD128-NEXT: v128.const $push[[R:[0-9]+]]=, ; SIMD128-SAME: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @@ -84,6 +85,7 @@ define i32 @extract_undef_v16i8_s(<16 x i8> %v) { ; CHECK-LABEL: extract_v16i8_u: ; NO-SIMD128-NOT: i8x16 +; SIMD128-VM-NOT: i8x16.extract_lane_u ; SIMD128-NEXT: .functype extract_v16i8_u (v128) -> (i32){{$}} ; SIMD128-NEXT: i8x16.extract_lane_u $push[[R:[0-9]+]]=, $0, 13{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} @@ -114,6 +116,7 @@ define i32 @extract_var_v16i8_u(<16 x i8> %v, i32 %i) { ; CHECK-LABEL: extract_undef_v16i8_u: ; NO-SIMD128-NOT: i8x16 +; SIMD128-VM-NOT: i8x16.extract_lane_u ; SIMD128-NEXT: .functype extract_undef_v16i8_u (v128) -> (i32){{$}} ; SIMD128-NEXT: i8x16.extract_lane_u $push[[R:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} @@ -126,7 +129,7 @@ define i32 @extract_undef_v16i8_u(<16 x i8> %v) { ; CHECK-LABEL: extract_v16i8: ; NO-SIMD128-NOT: i8x16 ; SIMD128-NEXT: .functype extract_v16i8 (v128) -> (i32){{$}} -; SIMD128-NEXT: i8x16.extract_lane_u $push[[R:[0-9]+]]=, $0, 13{{$}} +; SIMD128-NEXT: i8x16.extract_lane_s $push[[R:[0-9]+]]=, $0, 13{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define i8 @extract_v16i8(<16 x i8> %v) { %elem = extractelement <16 x i8> %v, i8 13 @@ -154,7 +157,7 @@ define i8 @extract_var_v16i8(<16 x i8> %v, i32 %i) { ; CHECK-LABEL: extract_undef_v16i8: ; NO-SIMD128-NOT: i8x16 ; SIMD128-NEXT: .functype extract_undef_v16i8 (v128) -> (i32){{$}} -; SIMD128-NEXT: i8x16.extract_lane_u $push[[R:[0-9]+]]=, $0, 0{{$}} +; SIMD128-NEXT: i8x16.extract_lane_s $push[[R:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define i8 @extract_undef_v16i8(<16 x i8> %v) { %elem = extractelement <16 x i8> %v, i8 undef @@ -347,6 +350,7 @@ define i32 @extract_undef_v8i16_s(<8 x i16> %v) { ; CHECK-LABEL: extract_v8i16_u: ; NO-SIMD128-NOT: i16x8 +; SIMD128-VM-NOT: i16x8.extract_lane_u ; SIMD128-NEXT: .functype extract_v8i16_u (v128) -> (i32){{$}} ; SIMD128-NEXT: i16x8.extract_lane_u $push[[R:[0-9]+]]=, $0, 5{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} @@ -379,6 +383,7 @@ define i32 @extract_var_v8i16_u(<8 x i16> %v, i32 %i) { ; CHECK-LABEL: extract_undef_v8i16_u: ; NO-SIMD128-NOT: i16x8 +; SIMD128-VM-NOT: i16x8.extract_lane_u ; SIMD128-NEXT: .functype extract_undef_v8i16_u (v128) -> (i32){{$}} ; SIMD128-NEXT: i16x8.extract_lane_u $push[[R:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} @@ -391,7 +396,7 @@ define i32 @extract_undef_v8i16_u(<8 x i16> %v) { ; CHECK-LABEL: extract_v8i16: ; NO-SIMD128-NOT: i16x8 ; SIMD128-NEXT: .functype extract_v8i16 (v128) -> (i32){{$}} -; SIMD128-NEXT: i16x8.extract_lane_u $push[[R:[0-9]+]]=, $0, 5{{$}} +; SIMD128-NEXT: i16x8.extract_lane_s $push[[R:[0-9]+]]=, $0, 5{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define i16 @extract_v8i16(<8 x i16> %v) { %elem = extractelement <8 x i16> %v, i16 5 @@ -421,7 +426,7 @@ define i16 @extract_var_v8i16(<8 x i16> %v, i32 %i) { ; CHECK-LABEL: extract_undef_v8i16: ; NO-SIMD128-NOT: i16x8 ; SIMD128-NEXT: .functype extract_undef_v8i16 (v128) -> (i32){{$}} -; SIMD128-NEXT: i16x8.extract_lane_u $push[[R:[0-9]+]]=, $0, 0{{$}} +; SIMD128-NEXT: i16x8.extract_lane_s $push[[R:[0-9]+]]=, $0, 0{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} define i16 @extract_undef_v8i16(<8 x i16> %v) { %elem = extractelement <8 x i16> %v, i16 undef