xref: /llvm-project/llvm/test/Transforms/LoopVectorize/RISCV/scalable-basics.ll (revision 2cf320d41ed708679e01eeeb93f58d6c5c88ba7a)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -loop-vectorize -scalable-vectorization=on -riscv-v-vector-bits-min=128 -mtriple riscv64-linux-gnu -mattr=+v,+f -S 2>%t | FileCheck %s -check-prefix=CHECK
3
4; A collection of fairly basic functional tests when both fixed and scalable vectorization is
5; allowed.  The primary goal of this is check for crashes during cost modeling, but it also
6; exercises the default heuristics in a useful way.
7
8target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
9target triple = "riscv64"
10
11define void @vector_add(ptr noalias nocapture %a, i64 %v, i64 %n) {
12; CHECK-LABEL: @vector_add(
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
15; CHECK:       vector.ph:
16; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[V:%.*]], i32 0
17; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer
18; CHECK-NEXT:    [[BROADCAST_SPLATINSERT2:%.*]] = insertelement <2 x i64> poison, i64 [[V]], i32 0
19; CHECK-NEXT:    [[BROADCAST_SPLAT3:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT2]], <2 x i64> poison, <2 x i32> zeroinitializer
20; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
21; CHECK:       vector.body:
22; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
23; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
24; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 2
25; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP0]]
26; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[TMP1]]
27; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP2]], i32 0
28; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP4]], align 8
29; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i64, ptr [[TMP2]], i32 2
30; CHECK-NEXT:    [[WIDE_LOAD1:%.*]] = load <2 x i64>, ptr [[TMP5]], align 8
31; CHECK-NEXT:    [[TMP6:%.*]] = add <2 x i64> [[WIDE_LOAD]], [[BROADCAST_SPLAT]]
32; CHECK-NEXT:    [[TMP7:%.*]] = add <2 x i64> [[WIDE_LOAD1]], [[BROADCAST_SPLAT3]]
33; CHECK-NEXT:    store <2 x i64> [[TMP6]], ptr [[TMP4]], align 8
34; CHECK-NEXT:    store <2 x i64> [[TMP7]], ptr [[TMP5]], align 8
35; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
36; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
37; CHECK-NEXT:    br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
38; CHECK:       middle.block:
39; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 1024, 1024
40; CHECK-NEXT:    br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]]
41; CHECK:       scalar.ph:
42; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
43; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
44; CHECK:       for.body:
45; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ]
46; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]]
47; CHECK-NEXT:    [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8
48; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[ELEM]], [[V]]
49; CHECK-NEXT:    store i64 [[ADD]], ptr [[ARRAYIDX]], align 8
50; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
51; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024
52; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]]
53; CHECK:       for.end:
54; CHECK-NEXT:    ret void
55;
56entry:
57  br label %for.body
58
59for.body:
60  %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
61  %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv
62  %elem = load i64, ptr %arrayidx
63  %add = add i64 %elem, %v
64  store i64 %add, ptr %arrayidx
65  %iv.next = add nuw nsw i64 %iv, 1
66  %exitcond.not = icmp eq i64 %iv.next, 1024
67  br i1 %exitcond.not, label %for.end, label %for.body
68
69for.end:
70  ret void
71}
72
73define void @splat_int(ptr noalias nocapture %a, i64 %v, i64 %n) {
74; CHECK-LABEL: @splat_int(
75; CHECK-NEXT:  entry:
76; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
77; CHECK:       vector.ph:
78; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[V:%.*]], i32 0
79; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer
80; CHECK-NEXT:    [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <2 x i64> poison, i64 [[V]], i32 0
81; CHECK-NEXT:    [[BROADCAST_SPLAT2:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT1]], <2 x i64> poison, <2 x i32> zeroinitializer
82; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
83; CHECK:       vector.body:
84; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
85; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
86; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 2
87; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP0]]
88; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[TMP1]]
89; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP2]], i32 0
90; CHECK-NEXT:    store <2 x i64> [[BROADCAST_SPLAT]], ptr [[TMP4]], align 8
91; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i64, ptr [[TMP2]], i32 2
92; CHECK-NEXT:    store <2 x i64> [[BROADCAST_SPLAT2]], ptr [[TMP5]], align 8
93; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
94; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
95; CHECK-NEXT:    br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
96; CHECK:       middle.block:
97; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 1024, 1024
98; CHECK-NEXT:    br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]]
99; CHECK:       scalar.ph:
100; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
101; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
102; CHECK:       for.body:
103; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ]
104; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]]
105; CHECK-NEXT:    store i64 [[V]], ptr [[ARRAYIDX]], align 8
106; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
107; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024
108; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
109; CHECK:       for.end:
110; CHECK-NEXT:    ret void
111;
112entry:
113  br label %for.body
114
115for.body:
116  %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
117  %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv
118  store i64 %v, ptr %arrayidx
119  %iv.next = add nuw nsw i64 %iv, 1
120  %exitcond.not = icmp eq i64 %iv.next, 1024
121  br i1 %exitcond.not, label %for.end, label %for.body
122
123for.end:
124  ret void
125}
126
127define void @splat_ptr(ptr noalias nocapture %a, ptr %v, i64 %n) {
128; CHECK-LABEL: @splat_ptr(
129; CHECK-NEXT:  entry:
130; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
131; CHECK:       vector.ph:
132; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x ptr> poison, ptr [[V:%.*]], i32 0
133; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x ptr> [[BROADCAST_SPLATINSERT]], <2 x ptr> poison, <2 x i32> zeroinitializer
134; CHECK-NEXT:    [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <2 x ptr> poison, ptr [[V]], i32 0
135; CHECK-NEXT:    [[BROADCAST_SPLAT2:%.*]] = shufflevector <2 x ptr> [[BROADCAST_SPLATINSERT1]], <2 x ptr> poison, <2 x i32> zeroinitializer
136; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
137; CHECK:       vector.body:
138; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
139; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
140; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 2
141; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP0]]
142; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[TMP1]]
143; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i32 0
144; CHECK-NEXT:    store <2 x ptr> [[BROADCAST_SPLAT]], ptr [[TMP4]], align 8
145; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds ptr, ptr [[TMP2]], i32 2
146; CHECK-NEXT:    store <2 x ptr> [[BROADCAST_SPLAT2]], ptr [[TMP5]], align 8
147; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
148; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
149; CHECK-NEXT:    br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
150; CHECK:       middle.block:
151; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 1024, 1024
152; CHECK-NEXT:    br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]]
153; CHECK:       scalar.ph:
154; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1024, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
155; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
156; CHECK:       for.body:
157; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ]
158; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]]
159; CHECK-NEXT:    store ptr [[V]], ptr [[ARRAYIDX]], align 8
160; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
161; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024
162; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]]
163; CHECK:       for.end:
164; CHECK-NEXT:    ret void
165;
166entry:
167  br label %for.body
168
169for.body:
170  %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
171  %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv
172  store ptr %v, ptr %arrayidx
173  %iv.next = add nuw nsw i64 %iv, 1
174  %exitcond.not = icmp eq i64 %iv.next, 1024
175  br i1 %exitcond.not, label %for.end, label %for.body
176
177for.end:
178  ret void
179}
180
181