xref: /llvm-project/llvm/test/Transforms/Scalarizer/vector-gep.ll (revision 2cb5c6d124d64344fd91eb769438fb81367bb266)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes='function(scalarizer)' %s | FileCheck %s
3
4; Check that the scalarizer can handle vector GEPs with scalar indices
5
6@vec = global <4 x ptr> <ptr null, ptr null, ptr null, ptr null>
7@index = global i16 1
8@ptr = global [4 x i16] [i16 1, i16 2, i16 3, i16 4]
9@ptrptr = global ptr null
10
11; constant index
12define void @test1() {
13; CHECK-LABEL: @test1(
14; CHECK-NEXT:  bb:
15; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x ptr>, ptr @vec, align 32
16; CHECK-NEXT:    [[DOTI0:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 0
17; CHECK-NEXT:    [[DOTI01:%.*]] = getelementptr i16, ptr [[DOTI0]], i16 1
18; CHECK-NEXT:    [[DOTI1:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 1
19; CHECK-NEXT:    [[DOTI12:%.*]] = getelementptr i16, ptr [[DOTI1]], i16 1
20; CHECK-NEXT:    [[DOTI2:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 2
21; CHECK-NEXT:    [[DOTI23:%.*]] = getelementptr i16, ptr [[DOTI2]], i16 1
22; CHECK-NEXT:    [[DOTI3:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 3
23; CHECK-NEXT:    [[DOTI34:%.*]] = getelementptr i16, ptr [[DOTI3]], i16 1
24; CHECK-NEXT:    ret void
25;
26bb:
27  %0 = load <4 x ptr>, ptr @vec
28  %1 = getelementptr i16, <4 x ptr> %0, i16 1
29
30  ret void
31}
32
33; non-constant index
34define void @test2() {
35; CHECK-LABEL: @test2(
36; CHECK-NEXT:  bb:
37; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x ptr>, ptr @vec, align 32
38; CHECK-NEXT:    [[DOTI0:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 0
39; CHECK-NEXT:    [[DOTI1:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 1
40; CHECK-NEXT:    [[DOTI2:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 2
41; CHECK-NEXT:    [[DOTI3:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 3
42; CHECK-NEXT:    [[INDEX:%.*]] = load i16, ptr @index, align 2
43; CHECK-NEXT:    [[DOTI01:%.*]] = getelementptr i16, ptr [[DOTI0]], i16 [[INDEX]]
44; CHECK-NEXT:    [[DOTI12:%.*]] = getelementptr i16, ptr [[DOTI1]], i16 [[INDEX]]
45; CHECK-NEXT:    [[DOTI23:%.*]] = getelementptr i16, ptr [[DOTI2]], i16 [[INDEX]]
46; CHECK-NEXT:    [[DOTI34:%.*]] = getelementptr i16, ptr [[DOTI3]], i16 [[INDEX]]
47; CHECK-NEXT:    ret void
48;
49bb:
50  %0 = load <4 x ptr>, ptr @vec
51  %index = load i16, ptr @index
52  %1 = getelementptr i16, <4 x ptr> %0, i16 %index
53
54  ret void
55}
56
57; Check that the scalarizer can handle vector GEPs with scalar pointer
58
59; constant pointer
60define <4 x ptr> @test3_constexpr() {
61; CHECK-LABEL: @test3_constexpr(
62; CHECK-NEXT:  bb:
63; CHECK-NEXT:    ret <4 x ptr> getelementptr (i16, ptr @ptr, <4 x i64> <i64 0, i64 1, i64 2, i64 3>)
64;
65bb:
66  ret <4 x ptr> getelementptr (i16, ptr @ptr, <4 x i64> <i64 0, i64 1, i64 2, i64 3>)
67}
68
69
70define <4 x ptr> @test3_constbase(i16 %idx) {
71; CHECK-LABEL: @test3_constbase(
72; CHECK-NEXT:  bb:
73; CHECK-NEXT:    [[OFFSET:%.*]] = getelementptr [4 x i16], ptr @ptr, i16 0, i16 [[IDX:%.*]]
74; CHECK-NEXT:    [[GEP_I0:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 0
75; CHECK-NEXT:    [[GEP_I1:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 1
76; CHECK-NEXT:    [[GEP_I2:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 2
77; CHECK-NEXT:    [[GEP_I3:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 3
78; CHECK-NEXT:    [[GEP_UPTO0:%.*]] = insertelement <4 x ptr> poison, ptr [[GEP_I0]], i64 0
79; CHECK-NEXT:    [[GEP_UPTO1:%.*]] = insertelement <4 x ptr> [[GEP_UPTO0]], ptr [[GEP_I1]], i64 1
80; CHECK-NEXT:    [[GEP_UPTO2:%.*]] = insertelement <4 x ptr> [[GEP_UPTO1]], ptr [[GEP_I2]], i64 2
81; CHECK-NEXT:    [[GEP:%.*]] = insertelement <4 x ptr> [[GEP_UPTO2]], ptr [[GEP_I3]], i64 3
82; CHECK-NEXT:    ret <4 x ptr> [[GEP]]
83;
84bb:
85  %offset = getelementptr [4 x i16], ptr @ptr, i16 0, i16 %idx
86  %gep = getelementptr i16, ptr %offset, <4 x i16> <i16 0, i16 1, i16 2, i16 3>
87  ret <4 x ptr> %gep
88}
89
90; Constant pointer with a variable vector offset
91define <4 x ptr> @test3_varoffset(<4 x i16> %offset) {
92; CHECK-LABEL: @test3_varoffset(
93; CHECK-NEXT:  bb:
94; CHECK-NEXT:    [[OFFSET_I0:%.*]] = extractelement <4 x i16> [[OFFSET:%.*]], i64 0
95; CHECK-NEXT:    [[GEP_I0:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I0]]
96; CHECK-NEXT:    [[OFFSET_I1:%.*]] = extractelement <4 x i16> [[OFFSET]], i64 1
97; CHECK-NEXT:    [[GEP_I1:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I1]]
98; CHECK-NEXT:    [[OFFSET_I2:%.*]] = extractelement <4 x i16> [[OFFSET]], i64 2
99; CHECK-NEXT:    [[GEP_I2:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I2]]
100; CHECK-NEXT:    [[OFFSET_I3:%.*]] = extractelement <4 x i16> [[OFFSET]], i64 3
101; CHECK-NEXT:    [[GEP_I3:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I3]]
102; CHECK-NEXT:    [[GEP_UPTO0:%.*]] = insertelement <4 x ptr> poison, ptr [[GEP_I0]], i64 0
103; CHECK-NEXT:    [[GEP_UPTO1:%.*]] = insertelement <4 x ptr> [[GEP_UPTO0]], ptr [[GEP_I1]], i64 1
104; CHECK-NEXT:    [[GEP_UPTO2:%.*]] = insertelement <4 x ptr> [[GEP_UPTO1]], ptr [[GEP_I2]], i64 2
105; CHECK-NEXT:    [[GEP:%.*]] = insertelement <4 x ptr> [[GEP_UPTO2]], ptr [[GEP_I3]], i64 3
106; CHECK-NEXT:    ret <4 x ptr> [[GEP]]
107;
108bb:
109  %gep = getelementptr i16, ptr @ptr, <4 x i16> %offset
110  ret <4 x ptr> %gep
111}
112
113; non-constant pointer
114define void @test4() {
115; CHECK-LABEL: @test4(
116; CHECK-NEXT:  bb:
117; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr @ptrptr, align 8
118; CHECK-NEXT:    [[DOTI0:%.*]] = getelementptr i16, ptr [[TMP0]], i16 0
119; CHECK-NEXT:    [[DOTI1:%.*]] = getelementptr i16, ptr [[TMP0]], i16 1
120; CHECK-NEXT:    [[DOTI2:%.*]] = getelementptr i16, ptr [[TMP0]], i16 2
121; CHECK-NEXT:    [[DOTI3:%.*]] = getelementptr i16, ptr [[TMP0]], i16 3
122; CHECK-NEXT:    ret void
123;
124bb:
125  %0 = load ptr, ptr @ptrptr
126  %1 = getelementptr i16, ptr %0, <4 x i16> <i16 0, i16 1, i16 2, i16 3>
127
128  ret void
129}
130
131; constant index, inbounds
132define void @test5() {
133; CHECK-LABEL: @test5(
134; CHECK-NEXT:  bb:
135; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x ptr>, ptr @vec, align 32
136; CHECK-NEXT:    [[DOTI0:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 0
137; CHECK-NEXT:    [[DOTI01:%.*]] = getelementptr inbounds i16, ptr [[DOTI0]], i16 1
138; CHECK-NEXT:    [[DOTI1:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 1
139; CHECK-NEXT:    [[DOTI12:%.*]] = getelementptr inbounds i16, ptr [[DOTI1]], i16 1
140; CHECK-NEXT:    [[DOTI2:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 2
141; CHECK-NEXT:    [[DOTI23:%.*]] = getelementptr inbounds i16, ptr [[DOTI2]], i16 1
142; CHECK-NEXT:    [[DOTI3:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 3
143; CHECK-NEXT:    [[DOTI34:%.*]] = getelementptr inbounds i16, ptr [[DOTI3]], i16 1
144; CHECK-NEXT:    ret void
145;
146bb:
147  %0 = load <4 x ptr>, ptr @vec
148  %1 = getelementptr inbounds i16, <4 x ptr> %0, i16 1
149
150  ret void
151}
152
153