| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: llc < %s -mtriple=wasm32 -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s | |
| define <8 x i32> @add_v8i8(<8 x i8> %a, <8 x i8> %b) { | |
| ; CHECK-LABEL: add_v8i8: | |
| ; CHECK: .functype add_v8i8 (i32, v128, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push2=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push3=, $pop2 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push0=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push1=, $pop0 | |
| ; CHECK-NEXT: i32x4.add $push4=, $pop3, $pop1 | |
| ; CHECK-NEXT: v128.store 0($0), $pop4 | |
| ; CHECK-NEXT: i8x16.shuffle $push11=, $1, $1, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| ; CHECK-NEXT: local.tee $push10=, $1=, $pop11 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push7=, $pop10 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push8=, $pop7 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push5=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push6=, $pop5 | |
| ; CHECK-NEXT: i32x4.add $push9=, $pop8, $pop6 | |
| ; CHECK-NEXT: v128.store 16($0), $pop9 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i8> %a to <8 x i32> | |
| %wide.b = zext <8 x i8> %a to <8 x i32> | |
| %res = add <8 x i32> %wide.a, %wide.b | |
| ret <8 x i32> %res | |
| } | |
| define <16 x i32> @add_v16i8(<16 x i8> %a, <16 x i8> %b) { | |
| ; CHECK-LABEL: add_v16i8: | |
| ; CHECK: .functype add_v16i8 (i32, v128, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_high_i8x16_s $push19=, $1 | |
| ; CHECK-NEXT: local.tee $push18=, $4=, $pop19 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push1=, $pop18 | |
| ; CHECK-NEXT: i16x8.extend_high_i8x16_u $push17=, $1 | |
| ; CHECK-NEXT: local.tee $push16=, $3=, $pop17 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_u $push0=, $pop16 | |
| ; CHECK-NEXT: i32x4.add $push2=, $pop1, $pop0 | |
| ; CHECK-NEXT: v128.store 48($0), $pop2 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push4=, $4 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push3=, $3 | |
| ; CHECK-NEXT: i32x4.add $push5=, $pop4, $pop3 | |
| ; CHECK-NEXT: v128.store 32($0), $pop5 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push15=, $1 | |
| ; CHECK-NEXT: local.tee $push14=, $4=, $pop15 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push7=, $pop14 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push13=, $1 | |
| ; CHECK-NEXT: local.tee $push12=, $1=, $pop13 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_u $push6=, $pop12 | |
| ; CHECK-NEXT: i32x4.add $push8=, $pop7, $pop6 | |
| ; CHECK-NEXT: v128.store 16($0), $pop8 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push10=, $4 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push9=, $1 | |
| ; CHECK-NEXT: i32x4.add $push11=, $pop10, $pop9 | |
| ; CHECK-NEXT: v128.store 0($0), $pop11 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <16 x i8> %a to <16 x i32> | |
| %wide.b = zext <16 x i8> %a to <16 x i32> | |
| %res = add <16 x i32> %wide.a, %wide.b | |
| ret <16 x i32> %res | |
| } | |
| define <8 x i32> @add_v8i16(<8 x i16> %a, <8 x i16> %b) { | |
| ; CHECK-LABEL: add_v8i16: | |
| ; CHECK: .functype add_v8i16 (i32, v128, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push5=, $1 | |
| ; CHECK-NEXT: local.tee $push4=, $3=, $pop5 | |
| ; CHECK-NEXT: i32x4.add $push0=, $pop4, $3 | |
| ; CHECK-NEXT: v128.store 16($0), $pop0 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push3=, $1 | |
| ; CHECK-NEXT: local.tee $push2=, $1=, $pop3 | |
| ; CHECK-NEXT: i32x4.add $push1=, $pop2, $1 | |
| ; CHECK-NEXT: v128.store 0($0), $pop1 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i16> %a to <8 x i32> | |
| %wide.b = sext <8 x i16> %a to <8 x i32> | |
| %res = add <8 x i32> %wide.a, %wide.b | |
| ret <8 x i32> %res | |
| } | |
| define <8 x i32> @sub_v8i8(<8 x i8> %a, <8 x i8> %b) { | |
| ; CHECK-LABEL: sub_v8i8: | |
| ; CHECK: .functype sub_v8i8 (i32, v128, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push2=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push3=, $pop2 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push0=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push1=, $pop0 | |
| ; CHECK-NEXT: i32x4.sub $push4=, $pop3, $pop1 | |
| ; CHECK-NEXT: v128.store 0($0), $pop4 | |
| ; CHECK-NEXT: i8x16.shuffle $push11=, $1, $1, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| ; CHECK-NEXT: local.tee $push10=, $1=, $pop11 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push7=, $pop10 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push8=, $pop7 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push5=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push6=, $pop5 | |
| ; CHECK-NEXT: i32x4.sub $push9=, $pop8, $pop6 | |
| ; CHECK-NEXT: v128.store 16($0), $pop9 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i8> %a to <8 x i32> | |
| %wide.b = zext <8 x i8> %a to <8 x i32> | |
| %res = sub <8 x i32> %wide.a, %wide.b | |
| ret <8 x i32> %res | |
| } | |
| define <16 x i32> @sub_v16i8(<16 x i8> %a, <16 x i8> %b) { | |
| ; CHECK-LABEL: sub_v16i8: | |
| ; CHECK: .functype sub_v16i8 (i32, v128, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_high_i8x16_s $push19=, $1 | |
| ; CHECK-NEXT: local.tee $push18=, $4=, $pop19 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push1=, $pop18 | |
| ; CHECK-NEXT: i16x8.extend_high_i8x16_u $push17=, $1 | |
| ; CHECK-NEXT: local.tee $push16=, $3=, $pop17 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_u $push0=, $pop16 | |
| ; CHECK-NEXT: i32x4.sub $push2=, $pop1, $pop0 | |
| ; CHECK-NEXT: v128.store 48($0), $pop2 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push4=, $4 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push3=, $3 | |
| ; CHECK-NEXT: i32x4.sub $push5=, $pop4, $pop3 | |
| ; CHECK-NEXT: v128.store 32($0), $pop5 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push15=, $1 | |
| ; CHECK-NEXT: local.tee $push14=, $4=, $pop15 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push7=, $pop14 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push13=, $1 | |
| ; CHECK-NEXT: local.tee $push12=, $1=, $pop13 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_u $push6=, $pop12 | |
| ; CHECK-NEXT: i32x4.sub $push8=, $pop7, $pop6 | |
| ; CHECK-NEXT: v128.store 16($0), $pop8 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push10=, $4 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push9=, $1 | |
| ; CHECK-NEXT: i32x4.sub $push11=, $pop10, $pop9 | |
| ; CHECK-NEXT: v128.store 0($0), $pop11 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <16 x i8> %a to <16 x i32> | |
| %wide.b = zext <16 x i8> %a to <16 x i32> | |
| %res = sub <16 x i32> %wide.a, %wide.b | |
| ret <16 x i32> %res | |
| } | |
| define <8 x i32> @sub_v8i16(<8 x i16> %a, <8 x i16> %b) { | |
| ; CHECK-LABEL: sub_v8i16: | |
| ; CHECK: .functype sub_v8i16 (i32, v128, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: v128.const $push1=, 0, 0, 0, 0 | |
| ; CHECK-NEXT: local.tee $push0=, $3=, $pop1 | |
| ; CHECK-NEXT: v128.store 16($0), $pop0 | |
| ; CHECK-NEXT: v128.store 0($0), $3 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i16> %a to <8 x i32> | |
| %wide.b = sext <8 x i16> %a to <8 x i32> | |
| %res = sub <8 x i32> %wide.a, %wide.b | |
| ret <8 x i32> %res | |
| } | |
| define <8 x i32> @ashr_v8i8(<8 x i8> %a) { | |
| ; CHECK-LABEL: ashr_v8i8: | |
| ; CHECK: .functype ashr_v8i8 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push0=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push1=, $pop0 | |
| ; CHECK-NEXT: i32.const $push2=, 4 | |
| ; CHECK-NEXT: i32x4.shr_s $push3=, $pop1, $pop2 | |
| ; CHECK-NEXT: v128.store 0($0), $pop3 | |
| ; CHECK-NEXT: i8x16.shuffle $push4=, $1, $1, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push5=, $pop4 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push6=, $pop5 | |
| ; CHECK-NEXT: i32.const $push8=, 4 | |
| ; CHECK-NEXT: i32x4.shr_s $push7=, $pop6, $pop8 | |
| ; CHECK-NEXT: v128.store 16($0), $pop7 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i8> %a to <8 x i32> | |
| %res = ashr <8 x i32> %wide.a, splat(i32 4) | |
| ret <8 x i32> %res | |
| } | |
| define <16 x i32> @ashr_v16i8(<16 x i8> %a) { | |
| ; CHECK-LABEL: ashr_v16i8: | |
| ; CHECK: .functype ashr_v16i8 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_high_i8x16_s $push15=, $1 | |
| ; CHECK-NEXT: local.tee $push14=, $2=, $pop15 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push0=, $pop14 | |
| ; CHECK-NEXT: i32.const $push1=, 1 | |
| ; CHECK-NEXT: i32x4.shr_s $push2=, $pop0, $pop1 | |
| ; CHECK-NEXT: v128.store 48($0), $pop2 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push3=, $2 | |
| ; CHECK-NEXT: i32.const $push13=, 1 | |
| ; CHECK-NEXT: i32x4.shr_s $push4=, $pop3, $pop13 | |
| ; CHECK-NEXT: v128.store 32($0), $pop4 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push12=, $1 | |
| ; CHECK-NEXT: local.tee $push11=, $1=, $pop12 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push5=, $pop11 | |
| ; CHECK-NEXT: i32.const $push10=, 1 | |
| ; CHECK-NEXT: i32x4.shr_s $push6=, $pop5, $pop10 | |
| ; CHECK-NEXT: v128.store 16($0), $pop6 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push7=, $1 | |
| ; CHECK-NEXT: i32.const $push9=, 1 | |
| ; CHECK-NEXT: i32x4.shr_s $push8=, $pop7, $pop9 | |
| ; CHECK-NEXT: v128.store 0($0), $pop8 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <16 x i8> %a to <16 x i32> | |
| %res = ashr <16 x i32> %wide.a, splat(i32 1) | |
| ret <16 x i32> %res | |
| } | |
| define <8 x i32> @ashr_v8i16(<8 x i16> %a) { | |
| ; CHECK-LABEL: ashr_v8i16: | |
| ; CHECK: .functype ashr_v8i16 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push0=, $1 | |
| ; CHECK-NEXT: i32.const $push1=, 8 | |
| ; CHECK-NEXT: i32x4.shr_s $push2=, $pop0, $pop1 | |
| ; CHECK-NEXT: v128.store 16($0), $pop2 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push3=, $1 | |
| ; CHECK-NEXT: i32.const $push5=, 8 | |
| ; CHECK-NEXT: i32x4.shr_s $push4=, $pop3, $pop5 | |
| ; CHECK-NEXT: v128.store 0($0), $pop4 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i16> %a to <8 x i32> | |
| %res = ashr <8 x i32> %wide.a, splat(i32 8) | |
| ret <8 x i32> %res | |
| } | |
| define <8 x i32> @lshr_v8i8(<8 x i8> %a) { | |
| ; CHECK-LABEL: lshr_v8i8: | |
| ; CHECK: .functype lshr_v8i8 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push0=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push1=, $pop0 | |
| ; CHECK-NEXT: i32.const $push2=, 4 | |
| ; CHECK-NEXT: i32x4.shr_u $push3=, $pop1, $pop2 | |
| ; CHECK-NEXT: v128.store 0($0), $pop3 | |
| ; CHECK-NEXT: i8x16.shuffle $push4=, $1, $1, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push5=, $pop4 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push6=, $pop5 | |
| ; CHECK-NEXT: i32.const $push8=, 4 | |
| ; CHECK-NEXT: i32x4.shr_u $push7=, $pop6, $pop8 | |
| ; CHECK-NEXT: v128.store 16($0), $pop7 | |
| ; CHECK-NEXT: return | |
| %wide.a = zext <8 x i8> %a to <8 x i32> | |
| %res = lshr <8 x i32> %wide.a, splat(i32 4) | |
| ret <8 x i32> %res | |
| } | |
| define <16 x i32> @lshr_v16i8(<16 x i8> %a) { | |
| ; CHECK-LABEL: lshr_v16i8: | |
| ; CHECK: .functype lshr_v16i8 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_high_i8x16_u $push15=, $1 | |
| ; CHECK-NEXT: local.tee $push14=, $2=, $pop15 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_u $push0=, $pop14 | |
| ; CHECK-NEXT: i32.const $push1=, 2 | |
| ; CHECK-NEXT: i32x4.shr_u $push2=, $pop0, $pop1 | |
| ; CHECK-NEXT: v128.store 48($0), $pop2 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push3=, $2 | |
| ; CHECK-NEXT: i32.const $push13=, 2 | |
| ; CHECK-NEXT: i32x4.shr_u $push4=, $pop3, $pop13 | |
| ; CHECK-NEXT: v128.store 32($0), $pop4 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_u $push12=, $1 | |
| ; CHECK-NEXT: local.tee $push11=, $1=, $pop12 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_u $push5=, $pop11 | |
| ; CHECK-NEXT: i32.const $push10=, 2 | |
| ; CHECK-NEXT: i32x4.shr_u $push6=, $pop5, $pop10 | |
| ; CHECK-NEXT: v128.store 16($0), $pop6 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push7=, $1 | |
| ; CHECK-NEXT: i32.const $push9=, 2 | |
| ; CHECK-NEXT: i32x4.shr_u $push8=, $pop7, $pop9 | |
| ; CHECK-NEXT: v128.store 0($0), $pop8 | |
| ; CHECK-NEXT: return | |
| %wide.a = zext <16 x i8> %a to <16 x i32> | |
| %res = lshr <16 x i32> %wide.a, splat(i32 2) | |
| ret <16 x i32> %res | |
| } | |
| define <8 x i32> @lshr_v8i16(<8 x i16> %a) { | |
| ; CHECK-LABEL: lshr_v8i16: | |
| ; CHECK: .functype lshr_v8i16 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_u $push0=, $1 | |
| ; CHECK-NEXT: i32.const $push1=, 7 | |
| ; CHECK-NEXT: i32x4.shr_u $push2=, $pop0, $pop1 | |
| ; CHECK-NEXT: v128.store 16($0), $pop2 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_u $push3=, $1 | |
| ; CHECK-NEXT: i32.const $push5=, 7 | |
| ; CHECK-NEXT: i32x4.shr_u $push4=, $pop3, $pop5 | |
| ; CHECK-NEXT: v128.store 0($0), $pop4 | |
| ; CHECK-NEXT: return | |
| %wide.a = zext <8 x i16> %a to <8 x i32> | |
| %res = lshr <8 x i32> %wide.a, splat(i32 7) | |
| ret <8 x i32> %res | |
| } | |
| define <8 x i32> @shl_v8i8(<8 x i8> %a) { | |
| ; CHECK-LABEL: shl_v8i8: | |
| ; CHECK: .functype shl_v8i8 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push0=, $1 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push1=, $pop0 | |
| ; CHECK-NEXT: i32.const $push2=, 3 | |
| ; CHECK-NEXT: i32x4.shl $push3=, $pop1, $pop2 | |
| ; CHECK-NEXT: v128.store 0($0), $pop3 | |
| ; CHECK-NEXT: i8x16.shuffle $push4=, $1, $1, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push5=, $pop4 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push6=, $pop5 | |
| ; CHECK-NEXT: i32.const $push8=, 3 | |
| ; CHECK-NEXT: i32x4.shl $push7=, $pop6, $pop8 | |
| ; CHECK-NEXT: v128.store 16($0), $pop7 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i8> %a to <8 x i32> | |
| %res = shl <8 x i32> %wide.a, splat(i32 3) | |
| ret <8 x i32> %res | |
| } | |
| define <16 x i32> @shl_v16i8(<16 x i8> %a) { | |
| ; CHECK-LABEL: shl_v16i8: | |
| ; CHECK: .functype shl_v16i8 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: i16x8.extend_high_i8x16_s $push15=, $1 | |
| ; CHECK-NEXT: local.tee $push14=, $2=, $pop15 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push0=, $pop14 | |
| ; CHECK-NEXT: i32.const $push1=, 5 | |
| ; CHECK-NEXT: i32x4.shl $push2=, $pop0, $pop1 | |
| ; CHECK-NEXT: v128.store 48($0), $pop2 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push3=, $2 | |
| ; CHECK-NEXT: i32.const $push13=, 5 | |
| ; CHECK-NEXT: i32x4.shl $push4=, $pop3, $pop13 | |
| ; CHECK-NEXT: v128.store 32($0), $pop4 | |
| ; CHECK-NEXT: i16x8.extend_low_i8x16_s $push12=, $1 | |
| ; CHECK-NEXT: local.tee $push11=, $1=, $pop12 | |
| ; CHECK-NEXT: i32x4.extend_high_i16x8_s $push5=, $pop11 | |
| ; CHECK-NEXT: i32.const $push10=, 5 | |
| ; CHECK-NEXT: i32x4.shl $push6=, $pop5, $pop10 | |
| ; CHECK-NEXT: v128.store 16($0), $pop6 | |
| ; CHECK-NEXT: i32x4.extend_low_i16x8_s $push7=, $1 | |
| ; CHECK-NEXT: i32.const $push9=, 5 | |
| ; CHECK-NEXT: i32x4.shl $push8=, $pop7, $pop9 | |
| ; CHECK-NEXT: v128.store 0($0), $pop8 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <16 x i8> %a to <16 x i32> | |
| %res = shl <16 x i32> %wide.a, splat (i32 5) | |
| ret <16 x i32> %res | |
| } | |
| define <8 x i32> @shl_v8i16(<8 x i16> %a) { | |
| ; CHECK-LABEL: shl_v8i16: | |
| ; CHECK: .functype shl_v8i16 (i32, v128) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: v128.const $push3=, 64, 64, 64, 64, 64, 64, 64, 64 | |
| ; CHECK-NEXT: local.tee $push2=, $2=, $pop3 | |
| ; CHECK-NEXT: i32x4.extmul_high_i16x8_s $push0=, $1, $pop2 | |
| ; CHECK-NEXT: v128.store 16($0), $pop0 | |
| ; CHECK-NEXT: i32x4.extmul_low_i16x8_s $push1=, $1, $2 | |
| ; CHECK-NEXT: v128.store 0($0), $pop1 | |
| ; CHECK-NEXT: return | |
| %wide.a = sext <8 x i16> %a to <8 x i32> | |
| %res = shl <8 x i32> %wide.a, splat(i32 6) | |
| ret <8 x i32> %res | |
| } | |
| define void @uhsub(ptr %src1, ptr %src2, ptr %dst) { | |
| ; CHECK-LABEL: uhsub: | |
| ; CHECK: .functype uhsub (i32, i32, i32) -> () | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: v128.load $6=, 0($0):p2align=0 | |
| ; CHECK-NEXT: v128.load $7=, 0($1):p2align=0 | |
| ; CHECK-NEXT: v128.load $push31=, 16($0):p2align=0 | |
| ; CHECK-NEXT: local.tee $push30=, $4=, $pop31 | |
| ; CHECK-NEXT: v128.const $push29=, 255, 255, 255, 255, 255, 255, 255, 255 | |
| ; CHECK-NEXT: local.tee $push28=, $5=, $pop29 | |
| ; CHECK-NEXT: v128.and $push7=, $pop30, $pop28 | |
| ; CHECK-NEXT: v128.load $push27=, 16($1):p2align=0 | |
| ; CHECK-NEXT: local.tee $push26=, $3=, $pop27 | |
| ; CHECK-NEXT: v128.and $push6=, $pop26, $5 | |
| ; CHECK-NEXT: i16x8.sub $push8=, $pop7, $pop6 | |
| ; CHECK-NEXT: i32.const $push4=, 1 | |
| ; CHECK-NEXT: i16x8.shr_u $push9=, $pop8, $pop4 | |
| ; CHECK-NEXT: i32.const $push0=, 8 | |
| ; CHECK-NEXT: i16x8.shr_u $push2=, $4, $pop0 | |
| ; CHECK-NEXT: i32.const $push25=, 8 | |
| ; CHECK-NEXT: i16x8.shr_u $push1=, $3, $pop25 | |
| ; CHECK-NEXT: i16x8.sub $push3=, $pop2, $pop1 | |
| ; CHECK-NEXT: i32.const $push24=, 1 | |
| ; CHECK-NEXT: i16x8.shr_u $push5=, $pop3, $pop24 | |
| ; CHECK-NEXT: i8x16.shuffle $push10=, $pop9, $pop5, 0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30 | |
| ; CHECK-NEXT: v128.store 16($2):p2align=0, $pop10 | |
| ; CHECK-NEXT: v128.and $push16=, $6, $5 | |
| ; CHECK-NEXT: v128.and $push15=, $7, $5 | |
| ; CHECK-NEXT: i16x8.sub $push17=, $pop16, $pop15 | |
| ; CHECK-NEXT: i32.const $push23=, 1 | |
| ; CHECK-NEXT: i16x8.shr_u $push18=, $pop17, $pop23 | |
| ; CHECK-NEXT: i32.const $push22=, 8 | |
| ; CHECK-NEXT: i16x8.shr_u $push12=, $6, $pop22 | |
| ; CHECK-NEXT: i32.const $push21=, 8 | |
| ; CHECK-NEXT: i16x8.shr_u $push11=, $7, $pop21 | |
| ; CHECK-NEXT: i16x8.sub $push13=, $pop12, $pop11 | |
| ; CHECK-NEXT: i32.const $push20=, 1 | |
| ; CHECK-NEXT: i16x8.shr_u $push14=, $pop13, $pop20 | |
| ; CHECK-NEXT: i8x16.shuffle $push19=, $pop18, $pop14, 0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30 | |
| ; CHECK-NEXT: v128.store 0($2):p2align=0, $pop19 | |
| ; CHECK-NEXT: return | |
| %i1 = getelementptr inbounds nuw i8, ptr %src1, i32 0 | |
| %wide.vec = load <32 x i8>, ptr %i1, align 1 | |
| %i2 = freeze <32 x i8> %wide.vec | |
| %i3 = bitcast <32 x i8> %i2 to <16 x i16> | |
| %i4 = bitcast <32 x i8> %i2 to <16 x i16> | |
| %i5 = and <16 x i16> %i4, splat (i16 255) | |
| %i6 = lshr <16 x i16> %i3, splat (i16 8) | |
| %i7 = getelementptr inbounds nuw i8, ptr %src2, i32 0 | |
| %wide.vec22 = load <32 x i8>, ptr %i7, align 1 | |
| %i8 = freeze <32 x i8> %wide.vec22 | |
| %i9 = bitcast <32 x i8> %i8 to <16 x i16> | |
| %i10 = bitcast <32 x i8> %i8 to <16 x i16> | |
| %i11 = and <16 x i16> %i10, splat (i16 255) | |
| %i12 = lshr <16 x i16> %i9, splat (i16 8) | |
| %i13 = sub nsw <16 x i16> %i5, %i11 | |
| %i14 = lshr <16 x i16> %i13, splat (i16 1) | |
| %i15 = getelementptr inbounds nuw i8, ptr %dst, i32 0 | |
| %i16 = sub nsw <16 x i16> %i6, %i12 | |
| %i17 = lshr <16 x i16> %i16, splat (i16 1) | |
| %i18 = shufflevector <16 x i16> %i14, <16 x i16> %i17, <32 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23, i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31> | |
| %interleaved.vec = trunc <32 x i16> %i18 to <32 x i8> | |
| store <32 x i8> %interleaved.vec, ptr %i15, align 1 | |
| ret void | |
| } |