blob: 35af3b5a7593488967a69ddfff4b51f7a01ac85f [file]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -p instsimplify -S | FileCheck %s
define <2 x i32> @left_undef_offset(<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: define <2 x i32> @left_undef_offset(
; CHECK-SAME: <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]) {
; CHECK-NEXT: ret <2 x i32> poison
;
%res = call <2 x i32> @llvm.vector.splice.left(<2 x i32> %a, <2 x i32> %b, i32 undef)
ret <2 x i32> %res
}
define <2 x i32> @right_undef_offset(<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: define <2 x i32> @right_undef_offset(
; CHECK-SAME: <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]) {
; CHECK-NEXT: ret <2 x i32> poison
;
%res = call <2 x i32> @llvm.vector.splice.right(<2 x i32> %a, <2 x i32> %b, i32 undef)
ret <2 x i32> %res
}
define <2 x i32> @left_out_of_bounds(<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: define <2 x i32> @left_out_of_bounds(
; CHECK-SAME: <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]) {
; CHECK-NEXT: ret <2 x i32> poison
;
%res = call <2 x i32> @llvm.vector.splice.left(<2 x i32> %a, <2 x i32> %b, i32 3)
ret <2 x i32> %res
}
define <2 x i32> @right_out_of_bounds(<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: define <2 x i32> @right_out_of_bounds(
; CHECK-SAME: <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]) {
; CHECK-NEXT: ret <2 x i32> poison
;
%res = call <2 x i32> @llvm.vector.splice.right(<2 x i32> %a, <2 x i32> %b, i32 3)
ret <2 x i32> %res
}
define <vscale x 2 x i32> @left_out_of_bounds_scalable(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) vscale_range(1, 1) {
; CHECK-LABEL: define <vscale x 2 x i32> @left_out_of_bounds_scalable(
; CHECK-SAME: <vscale x 2 x i32> [[A:%.*]], <vscale x 2 x i32> [[B:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: ret <vscale x 2 x i32> poison
;
%res = call <vscale x 2 x i32> @llvm.vector.splice.left(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b, i32 3)
ret <vscale x 2 x i32> %res
}
define <vscale x 2 x i32> @left_not_out_of_bounds_scalable(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) {
; CHECK-LABEL: define <vscale x 2 x i32> @left_not_out_of_bounds_scalable(
; CHECK-SAME: <vscale x 2 x i32> [[A:%.*]], <vscale x 2 x i32> [[B:%.*]]) {
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 2 x i32> @llvm.vector.splice.left.nxv2i32(<vscale x 2 x i32> [[A]], <vscale x 2 x i32> [[B]], i32 3)
; CHECK-NEXT: ret <vscale x 2 x i32> [[RES]]
;
%res = call <vscale x 2 x i32> @llvm.vector.splice.left(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b, i32 3)
ret <vscale x 2 x i32> %res
}
define <vscale x 2 x i32> @right_out_of_bounds_scalable(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) vscale_range(1, 1) {
; CHECK-LABEL: define <vscale x 2 x i32> @right_out_of_bounds_scalable(
; CHECK-SAME: <vscale x 2 x i32> [[A:%.*]], <vscale x 2 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: ret <vscale x 2 x i32> poison
;
%res = call <vscale x 2 x i32> @llvm.vector.splice.right(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b, i32 3)
ret <vscale x 2 x i32> %res
}
define <vscale x 2 x i32> @right_not_out_of_bounds_scalable(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) {
; CHECK-LABEL: define <vscale x 2 x i32> @right_not_out_of_bounds_scalable(
; CHECK-SAME: <vscale x 2 x i32> [[A:%.*]], <vscale x 2 x i32> [[B:%.*]]) {
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 2 x i32> @llvm.vector.splice.right.nxv2i32(<vscale x 2 x i32> [[A]], <vscale x 2 x i32> [[B]], i32 3)
; CHECK-NEXT: ret <vscale x 2 x i32> [[RES]]
;
%res = call <vscale x 2 x i32> @llvm.vector.splice.right(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b, i32 3)
ret <vscale x 2 x i32> %res
}
define <2 x i32> @left_offset_0(<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: define <2 x i32> @left_offset_0(
; CHECK-SAME: <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]) {
; CHECK-NEXT: ret <2 x i32> [[A]]
;
%res = call <2 x i32> @llvm.vector.splice.left(<2 x i32> %a, <2 x i32> %b, i32 0)
ret <2 x i32> %res
}
define <2 x i32> @right_offset_0(<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: define <2 x i32> @right_offset_0(
; CHECK-SAME: <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]) {
; CHECK-NEXT: ret <2 x i32> [[B]]
;
%res = call <2 x i32> @llvm.vector.splice.right(<2 x i32> %a, <2 x i32> %b, i32 0)
ret <2 x i32> %res
}
; Tests for folding splice.right(splice.left(poison, x, offset), poison, offset) -> x
; Construct splice roundtrip on input and return it with set offset of 2
define <4 x i32> @splice_left_right_cancel_offset_2(<4 x i32> %a) {
; CHECK-LABEL: define <4 x i32> @splice_left_right_cancel_offset_2(
; CHECK-SAME: <4 x i32> [[A:%.*]]) {
; CHECK-NEXT: ret <4 x i32> [[A]]
;
%l = call <4 x i32> @llvm.vector.splice.left(<4 x i32> poison, <4 x i32> %a, i32 2)
%r = call <4 x i32> @llvm.vector.splice.right(<4 x i32> %l, <4 x i32> poison, i32 2)
ret <4 x i32> %r
}
; Construct splice roundtrip on input and return it with set offset of 0
define <4 x i32> @splice_left_right_cancel_offset_0(<4 x i32> %a) {
; CHECK-LABEL: define <4 x i32> @splice_left_right_cancel_offset_0(
; CHECK-SAME: <4 x i32> [[A:%.*]]) {
; CHECK-NEXT: ret <4 x i32> poison
;
%l = call <4 x i32> @llvm.vector.splice.left(<4 x i32> poison, <4 x i32> %a, i32 0)
%r = call <4 x i32> @llvm.vector.splice.right(<4 x i32> %l, <4 x i32> poison, i32 0)
ret <4 x i32> %r
}
define <4 x i32> @splice_left_right_cancel_offset_dynamic(<4 x i32> %a, i32 %offset) {
; CHECK-LABEL: define <4 x i32> @splice_left_right_cancel_offset_dynamic(
; CHECK-SAME: <4 x i32> [[A:%.*]], i32 [[OFFSET:%.*]]) {
; CHECK-NEXT: ret <4 x i32> [[A]]
;
%l = call <4 x i32> @llvm.vector.splice.left(<4 x i32> poison, <4 x i32> %a, i32 %offset)
%r = call <4 x i32> @llvm.vector.splice.right(<4 x i32> %l, <4 x i32> poison, i32 %offset)
ret <4 x i32> %r
}
define <vscale x 4 x i32> @splice_left_right_cancel_offset_2_scalable(<vscale x 4 x i32> %a) {
; CHECK-LABEL: define <vscale x 4 x i32> @splice_left_right_cancel_offset_2_scalable(
; CHECK-SAME: <vscale x 4 x i32> [[A:%.*]]) {
; CHECK-NEXT: ret <vscale x 4 x i32> [[A]]
;
%l = call <vscale x 4 x i32> @llvm.vector.splice.left(<vscale x 4 x i32> poison, <vscale x 4 x i32> %a, i32 2)
%r = call <vscale x 4 x i32> @llvm.vector.splice.right(<vscale x 4 x i32> %l, <vscale x 4 x i32> poison, i32 2)
ret <vscale x 4 x i32> %r
}
define <4 x i32> @splice_left_right_non_poison_outer(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define <4 x i32> @splice_left_right_non_poison_outer(
; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
; CHECK-NEXT: [[L:%.*]] = call <4 x i32> @llvm.vector.splice.left.v4i32(<4 x i32> poison, <4 x i32> [[A]], i32 2)
; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.vector.splice.right.v4i32(<4 x i32> [[L]], <4 x i32> [[B]], i32 2)
; CHECK-NEXT: ret <4 x i32> [[R]]
;
%l = call <4 x i32> @llvm.vector.splice.left(<4 x i32> poison, <4 x i32> %a, i32 2)
%r = call <4 x i32> @llvm.vector.splice.right(<4 x i32> %l, <4 x i32> %b, i32 2)
ret <4 x i32> %r
}
; Different offsets
define <4 x i32> @splice_left_right_cancel_mismatch_offset(<4 x i32> %a) {
; CHECK-LABEL: define <4 x i32> @splice_left_right_cancel_mismatch_offset(
; CHECK-SAME: <4 x i32> [[A:%.*]]) {
; CHECK-NEXT: [[L:%.*]] = call <4 x i32> @llvm.vector.splice.left.v4i32(<4 x i32> poison, <4 x i32> [[A]], i32 2)
; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.vector.splice.right.v4i32(<4 x i32> [[L]], <4 x i32> poison, i32 1)
; CHECK-NEXT: ret <4 x i32> [[R]]
;
%l = call <4 x i32> @llvm.vector.splice.left(<4 x i32> poison, <4 x i32> %a, i32 2)
%r = call <4 x i32> @llvm.vector.splice.right(<4 x i32> %l, <4 x i32> poison, i32 1)
ret <4 x i32> %r
}
define <4 x i32> @splice_right_then_left(<4 x i32> %a) {
; CHECK-LABEL: define <4 x i32> @splice_right_then_left(
; CHECK-SAME: <4 x i32> [[A:%.*]]) {
; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.vector.splice.right.v4i32(<4 x i32> poison, <4 x i32> [[A]], i32 2)
; CHECK-NEXT: [[L:%.*]] = call <4 x i32> @llvm.vector.splice.left.v4i32(<4 x i32> [[R]], <4 x i32> poison, i32 2)
; CHECK-NEXT: ret <4 x i32> [[L]]
;
%r = call <4 x i32> @llvm.vector.splice.right(<4 x i32> poison, <4 x i32> %a, i32 2)
%l = call <4 x i32> @llvm.vector.splice.left(<4 x i32> %r, <4 x i32> poison, i32 2)
ret <4 x i32> %l
}