xref: /llvm-project/llvm/test/Transforms/InstCombine/canonicalize-vector-extract.ll (revision b0cc47c959cb4c4ab54516ee73ede52d208a739f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; llvm.vector.extract canonicalizes to shufflevector in the fixed case. In the
5; scalable case, we lower to the EXTRACT_SUBVECTOR ISD node.
6
7declare <10 x i32> @llvm.vector.extract.v10i32.v8i32(<8 x i32> %vec, i64 %idx)
8declare <2 x i32> @llvm.vector.extract.v2i32.v4i32(<8 x i32> %vec, i64 %idx)
9declare <3 x i32> @llvm.vector.extract.v3i32.v8i32(<8 x i32> %vec, i64 %idx)
10declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32> %vec, i64 %idx)
11declare <4 x i32> @llvm.vector.extract.v4i32.v8i32(<8 x i32> %vec, i64 %idx)
12declare <8 x i32> @llvm.vector.extract.v8i32.v8i32(<8 x i32> %vec, i64 %idx)
13declare <vscale x 8 x i32> @llvm.vector.extract.nxv8i32.nxv8i32(<vscale x 8 x i32> %vec, i64 %idx)
14
15; ============================================================================ ;
16; Trivial cases
17; ============================================================================ ;
18
19; Extracting the entirety of a vector is a nop.
20define <8 x i32> @trivial_nop(<8 x i32> %vec) {
21; CHECK-LABEL: @trivial_nop(
22; CHECK-NEXT:    ret <8 x i32> [[VEC:%.*]]
23;
24  %1 = call <8 x i32> @llvm.vector.extract.v8i32.v8i32(<8 x i32> %vec, i64 0)
25  ret <8 x i32> %1
26}
27
28define <vscale x 8 x i32> @trivial_nop_scalable(<vscale x 8 x i32> %vec) {
29; CHECK-LABEL: define <vscale x 8 x i32> @trivial_nop_scalable(
30; CHECK-SAME: <vscale x 8 x i32> [[VEC:%.*]]) {
31; CHECK-NEXT:    ret <vscale x 8 x i32> [[VEC]]
32;
33  %ext = call <vscale x 8 x i32> @llvm.vector.extract.nxv8i32.nxv8i32(<vscale x 8 x i32> %vec, i64 0)
34  ret <vscale x 8 x i32> %ext
35}
36
37; ============================================================================ ;
38; Valid canonicalizations
39; ============================================================================ ;
40
41define <2 x i32> @valid_extraction_a(<8 x i32> %vec) {
42; CHECK-LABEL: @valid_extraction_a(
43; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <2 x i32> <i32 0, i32 1>
44; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
45;
46  %1 = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<8 x i32> %vec, i64 0)
47  ret <2 x i32> %1
48}
49
50define <2 x i32> @valid_extraction_b(<8 x i32> %vec) {
51; CHECK-LABEL: @valid_extraction_b(
52; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <2 x i32> <i32 2, i32 3>
53; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
54;
55  %1 = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<8 x i32> %vec, i64 2)
56  ret <2 x i32> %1
57}
58
59define <2 x i32> @valid_extraction_c(<8 x i32> %vec) {
60; CHECK-LABEL: @valid_extraction_c(
61; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <2 x i32> <i32 4, i32 5>
62; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
63;
64  %1 = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<8 x i32> %vec, i64 4)
65  ret <2 x i32> %1
66}
67
68define <2 x i32> @valid_extraction_d(<8 x i32> %vec) {
69; CHECK-LABEL: @valid_extraction_d(
70; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <2 x i32> <i32 6, i32 7>
71; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
72;
73  %1 = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<8 x i32> %vec, i64 6)
74  ret <2 x i32> %1
75}
76
77define <4 x i32> @valid_extraction_e(<8 x i32> %vec) {
78; CHECK-LABEL: @valid_extraction_e(
79; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
80; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
81;
82  %1 = call <4 x i32> @llvm.vector.extract.v4i32.v8i32(<8 x i32> %vec, i64 0)
83  ret <4 x i32> %1
84}
85
86define <4 x i32> @valid_extraction_f(<8 x i32> %vec) {
87; CHECK-LABEL: @valid_extraction_f(
88; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
89; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
90;
91  %1 = call <4 x i32> @llvm.vector.extract.v4i32.v8i32(<8 x i32> %vec, i64 4)
92  ret <4 x i32> %1
93}
94
95define <3 x i32> @valid_extraction_g(<8 x i32> %vec) {
96; CHECK-LABEL: @valid_extraction_g(
97; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
98; CHECK-NEXT:    ret <3 x i32> [[TMP1]]
99;
100  %1 = call <3 x i32> @llvm.vector.extract.v3i32.v8i32(<8 x i32> %vec, i64 0)
101  ret <3 x i32> %1
102}
103
104define <3 x i32> @valid_extraction_h(<8 x i32> %vec) {
105; CHECK-LABEL: @valid_extraction_h(
106; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i32> [[VEC:%.*]], <8 x i32> poison, <3 x i32> <i32 3, i32 4, i32 5>
107; CHECK-NEXT:    ret <3 x i32> [[TMP1]]
108;
109  %1 = call <3 x i32> @llvm.vector.extract.v3i32.v8i32(<8 x i32> %vec, i64 3)
110  ret <3 x i32> %1
111}
112
113; ============================================================================ ;
114; Scalable cases
115; ============================================================================ ;
116
117; Scalable extractions should not be canonicalized. This will be lowered to the
118; EXTRACT_SUBVECTOR ISD node later.
119define <4 x i32> @scalable_extract(<vscale x 4 x i32> %vec) {
120; CHECK-LABEL: @scalable_extract(
121; CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32> [[VEC:%.*]], i64 0)
122; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
123;
124  %1 = call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32> %vec, i64 0)
125  ret <4 x i32> %1
126}
127