| ; 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 |
| } |