Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / Thumb2 / mve-pipelineloops.ll
blob70957ca950d71fc18b98581f6efb62f25ea37545
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -O3 -mattr=+mve.fp,+use-mipipeliner -mcpu=cortex-m55 %s -o - -verify-machineinstrs --pipeliner-force-issue-width=10 | FileCheck %s
4 define void @arm_cmplx_dot_prod_q15(ptr noundef %pSrcA, ptr noundef %pSrcB, i32 noundef %numSamples, ptr nocapture noundef writeonly %realResult, ptr nocapture noundef writeonly %imagResult) {
5 ; CHECK-LABEL: arm_cmplx_dot_prod_q15:
6 ; CHECK:       @ %bb.0: @ %entry
7 ; CHECK-NEXT:    .save {r4, r5, r6, r7, r8, lr}
8 ; CHECK-NEXT:    push.w {r4, r5, r6, r7, r8, lr}
9 ; CHECK-NEXT:    ldr.w r12, [sp, #24]
10 ; CHECK-NEXT:    cmp r2, #16
11 ; CHECK-NEXT:    blo .LBB0_5
12 ; CHECK-NEXT:  @ %bb.1: @ %while.body.preheader
13 ; CHECK-NEXT:    movs r6, #2
14 ; CHECK-NEXT:    lsrs r7, r2, #3
15 ; CHECK-NEXT:    rsb r6, r6, r2, lsr #3
16 ; CHECK-NEXT:    movs r5, #0
17 ; CHECK-NEXT:    cmp r7, #2
18 ; CHECK-NEXT:    csel r7, r6, r5, hs
19 ; CHECK-NEXT:    add.w lr, r7, #1
20 ; CHECK-NEXT:    mov r4, r5
21 ; CHECK-NEXT:    vldrh.u16 q0, [r0], #32
22 ; CHECK-NEXT:    movs r7, #0
23 ; CHECK-NEXT:    mov r8, r5
24 ; CHECK-NEXT:    vldrh.u16 q1, [r1], #32
25 ; CHECK-NEXT:    vmlsldava.s16 r4, r7, q0, q1
26 ; CHECK-NEXT:    vldrh.u16 q2, [r0, #-16]
27 ; CHECK-NEXT:    vmlaldavax.s16 r8, r5, q0, q1
28 ; CHECK-NEXT:    vldrh.u16 q3, [r1, #-16]
29 ; CHECK-NEXT:    vmlsldava.s16 r4, r7, q2, q3
30 ; CHECK-NEXT:    vldrh.u16 q0, [r1], #32
31 ; CHECK-NEXT:    sub.w lr, lr, #1
32 ; CHECK-NEXT:    cmp.w lr, #0
33 ; CHECK-NEXT:    vldrh.u16 q1, [r0], #32
34 ; CHECK-NEXT:    beq .LBB0_3
35 ; CHECK-NEXT:    .p2align 2
36 ; CHECK-NEXT:  .LBB0_2: @ %while.body
37 ; CHECK-NEXT:    @ =>This Inner Loop Header: Depth=1
38 ; CHECK-NEXT:    vmlaldavax.s16 r8, r5, q2, q3
39 ; CHECK-NEXT:    vldrh.u16 q3, [r1, #-16]
40 ; CHECK-NEXT:    vmlsldava.s16 r4, r7, q1, q0
41 ; CHECK-NEXT:    vldrh.u16 q2, [r0, #-16]
42 ; CHECK-NEXT:    vmlaldavax.s16 r8, r5, q1, q0
43 ; CHECK-NEXT:    vldrh.u16 q1, [r0], #32
44 ; CHECK-NEXT:    vmlsldava.s16 r4, r7, q2, q3
45 ; CHECK-NEXT:    vldrh.u16 q0, [r1], #32
46 ; CHECK-NEXT:    le lr, .LBB0_2
47 ; CHECK-NEXT:  .LBB0_3:
48 ; CHECK-NEXT:    vmlaldavax.s16 r8, r5, q2, q3
49 ; CHECK-NEXT:    movs r6, #14
50 ; CHECK-NEXT:    and.w r2, r6, r2, lsl #1
51 ; CHECK-NEXT:    vmlaldavax.s16 r8, r5, q1, q0
52 ; CHECK-NEXT:    vldrh.u16 q2, [r0, #-16]
53 ; CHECK-NEXT:    vmlsldava.s16 r4, r7, q1, q0
54 ; CHECK-NEXT:    vldrh.u16 q0, [r1, #-16]
55 ; CHECK-NEXT:    vmlaldavax.s16 r8, r5, q2, q0
56 ; CHECK-NEXT:    vctp.16 r2
57 ; CHECK-NEXT:    vmlsldava.s16 r4, r7, q2, q0
58 ; CHECK-NEXT:    vpst
59 ; CHECK-NEXT:    vldrht.u16 q1, [r0]
60 ; CHECK-NEXT:    cmp r2, #9
61 ; CHECK-NEXT:    vpsttt
62 ; CHECK-NEXT:    vldrht.u16 q0, [r1]
63 ; CHECK-NEXT:    vmlsldavat.s16 r4, r7, q1, q0
64 ; CHECK-NEXT:    vmlaldavaxt.s16 r8, r5, q1, q0
65 ; CHECK-NEXT:    blo .LBB0_10
66 ; CHECK-NEXT:  @ %bb.4: @ %do.body.1
67 ; CHECK-NEXT:    subs r2, #8
68 ; CHECK-NEXT:    vctp.16 r2
69 ; CHECK-NEXT:    vpstttt
70 ; CHECK-NEXT:    vldrht.u16 q0, [r0, #16]
71 ; CHECK-NEXT:    vldrht.u16 q1, [r1, #16]
72 ; CHECK-NEXT:    vmlsldavat.s16 r4, r7, q0, q1
73 ; CHECK-NEXT:    vmlaldavaxt.s16 r8, r5, q0, q1
74 ; CHECK-NEXT:    b .LBB0_10
75 ; CHECK-NEXT:    .p2align 2
76 ; CHECK-NEXT:  .LBB0_5: @ %if.else
77 ; CHECK-NEXT:    mov.w r4, #0
78 ; CHECK-NEXT:    cbz r2, .LBB0_9
79 ; CHECK-NEXT:  @ %bb.6: @ %while.body14.preheader
80 ; CHECK-NEXT:    lsls r6, r2, #1
81 ; CHECK-NEXT:    mov r5, r4
82 ; CHECK-NEXT:    mov r7, r4
83 ; CHECK-NEXT:    movs r2, #0
84 ; CHECK-NEXT:    dlstp.16 lr, r6
85 ; CHECK-NEXT:    .p2align 2
86 ; CHECK-NEXT:  .LBB0_7: @ %while.body14
87 ; CHECK-NEXT:    @ =>This Inner Loop Header: Depth=1
88 ; CHECK-NEXT:    vldrh.u16 q0, [r0], #16
89 ; CHECK-NEXT:    vldrh.u16 q1, [r1], #16
90 ; CHECK-NEXT:    vmlsldava.s16 r2, r7, q0, q1
91 ; CHECK-NEXT:    vmlaldavax.s16 r4, r5, q0, q1
92 ; CHECK-NEXT:    letp lr, .LBB0_7
93 ; CHECK-NEXT:  @ %bb.8: @ %if.end.loopexit177
94 ; CHECK-NEXT:    mov r8, r4
95 ; CHECK-NEXT:    mov r4, r2
96 ; CHECK-NEXT:    b .LBB0_10
97 ; CHECK-NEXT:    .p2align 2
98 ; CHECK-NEXT:  .LBB0_9:
99 ; CHECK-NEXT:    mov r7, r4
100 ; CHECK-NEXT:    mov.w r8, #0
101 ; CHECK-NEXT:    mov r5, r4
102 ; CHECK-NEXT:  .LBB0_10: @ %if.end
103 ; CHECK-NEXT:    asrl r4, r7, #6
104 ; CHECK-NEXT:    asrl r8, r5, #6
105 ; CHECK-NEXT:    str r4, [r3]
106 ; CHECK-NEXT:    str.w r8, [r12]
107 ; CHECK-NEXT:    pop.w {r4, r5, r6, r7, r8, pc}
108 entry:
109   %cmp = icmp ugt i32 %numSamples, 15
110   br i1 %cmp, label %while.body.preheader, label %if.else
112 while.body.preheader:                             ; preds = %entry
113   %vecSrcA.0138 = load <8 x i16>, ptr %pSrcA, align 2
114   %vecSrcB.0137 = load <8 x i16>, ptr %pSrcB, align 2
115   %pSrcB.addr.0136 = getelementptr inbounds i16, ptr %pSrcB, i32 8
116   %pSrcA.addr.0135 = getelementptr inbounds i16, ptr %pSrcA, i32 8
117   %shr = lshr i32 %numSamples, 3
118   br label %while.body
120 while.body:                                       ; preds = %while.body.preheader, %while.body
121   %vecSrcA.0150 = phi <8 x i16> [ %vecSrcA.0, %while.body ], [ %vecSrcA.0138, %while.body.preheader ]
122   %vecSrcB.0149 = phi <8 x i16> [ %vecSrcB.0, %while.body ], [ %vecSrcB.0137, %while.body.preheader ]
123   %pSrcB.addr.0148 = phi ptr [ %pSrcB.addr.0, %while.body ], [ %pSrcB.addr.0136, %while.body.preheader ]
124   %pSrcA.addr.0147 = phi ptr [ %pSrcA.addr.0, %while.body ], [ %pSrcA.addr.0135, %while.body.preheader ]
125   %vecSrcB.0.in146 = phi ptr [ %add.ptr4, %while.body ], [ %pSrcB, %while.body.preheader ]
126   %vecSrcA.0.in145 = phi ptr [ %add.ptr3, %while.body ], [ %pSrcA, %while.body.preheader ]
127   %accImag.0.off32144 = phi i32 [ %12, %while.body ], [ 0, %while.body.preheader ]
128   %accImag.0.off0143 = phi i32 [ %13, %while.body ], [ 0, %while.body.preheader ]
129   %accReal.0.off32142 = phi i32 [ %9, %while.body ], [ 0, %while.body.preheader ]
130   %accReal.0.off0141 = phi i32 [ %10, %while.body ], [ 0, %while.body.preheader ]
131   %blkCnt.0.in140 = phi i32 [ %blkCnt.0, %while.body ], [ %shr, %while.body.preheader ]
132   %blkCnt.0 = add nsw i32 %blkCnt.0.in140, -1
133   %0 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 1, i32 0, i32 %accReal.0.off0141, i32 %accReal.0.off32142, <8 x i16> %vecSrcA.0150, <8 x i16> %vecSrcB.0149)
134   %1 = extractvalue { i32, i32 } %0, 1
135   %2 = extractvalue { i32, i32 } %0, 0
136   %3 = load <8 x i16>, ptr %pSrcA.addr.0147, align 2
137   %add.ptr3 = getelementptr inbounds i16, ptr %vecSrcA.0.in145, i32 16
138   %4 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 0, i32 1, i32 %accImag.0.off0143, i32 %accImag.0.off32144, <8 x i16> %vecSrcA.0150, <8 x i16> %vecSrcB.0149)
139   %5 = extractvalue { i32, i32 } %4, 1
140   %6 = extractvalue { i32, i32 } %4, 0
141   %7 = load <8 x i16>, ptr %pSrcB.addr.0148, align 2
142   %add.ptr4 = getelementptr inbounds i16, ptr %vecSrcB.0.in146, i32 16
143   %8 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 1, i32 0, i32 %2, i32 %1, <8 x i16> %3, <8 x i16> %7)
144   %9 = extractvalue { i32, i32 } %8, 1
145   %10 = extractvalue { i32, i32 } %8, 0
146   %11 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 0, i32 1, i32 %6, i32 %5, <8 x i16> %3, <8 x i16> %7)
147   %12 = extractvalue { i32, i32 } %11, 1
148   %13 = extractvalue { i32, i32 } %11, 0
149   %pSrcA.addr.0 = getelementptr inbounds i16, ptr %vecSrcA.0.in145, i32 24
150   %pSrcB.addr.0 = getelementptr inbounds i16, ptr %vecSrcB.0.in146, i32 24
151   %vecSrcB.0 = load <8 x i16>, ptr %add.ptr4, align 2
152   %vecSrcA.0 = load <8 x i16>, ptr %add.ptr3, align 2
153   %cmp2 = icmp ugt i32 %blkCnt.0.in140, 2
154   br i1 %cmp2, label %while.body, label %do.body
156 do.body:                                          ; preds = %while.body
157   %and = shl i32 %numSamples, 1
158   %mul = and i32 %and, 14
159   %14 = extractvalue { i32, i32 } %11, 0
160   %15 = extractvalue { i32, i32 } %11, 1
161   %16 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 0, i32 1, i32 %14, i32 %15, <8 x i16> %vecSrcA.0, <8 x i16> %vecSrcB.0)
162   %17 = extractvalue { i32, i32 } %16, 0
163   %18 = extractvalue { i32, i32 } %16, 1
164   %19 = load <8 x i16>, ptr %pSrcA.addr.0, align 2
165   %20 = load <8 x i16>, ptr %pSrcB.addr.0, align 2
166   %21 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 0, i32 1, i32 %17, i32 %18, <8 x i16> %19, <8 x i16> %20)
167   %22 = extractvalue { i32, i32 } %8, 0
168   %23 = extractvalue { i32, i32 } %8, 1
169   %24 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 1, i32 0, i32 %22, i32 %23, <8 x i16> %vecSrcA.0, <8 x i16> %vecSrcB.0)
170   %25 = extractvalue { i32, i32 } %24, 0
171   %26 = extractvalue { i32, i32 } %24, 1
172   %27 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32 0, i32 1, i32 0, i32 %25, i32 %26, <8 x i16> %19, <8 x i16> %20)
173   %accImag.1.off32 = extractvalue { i32, i32 } %21, 1
174   %accImag.1.off0 = extractvalue { i32, i32 } %21, 0
175   %accReal.1.off32 = extractvalue { i32, i32 } %27, 1
176   %accReal.1.off0 = extractvalue { i32, i32 } %27, 0
177   %28 = tail call <8 x i1> @llvm.arm.mve.vctp16(i32 %mul)
178   %add.ptr7 = getelementptr inbounds i16, ptr %vecSrcA.0.in145, i32 32
179   %add.ptr8 = getelementptr inbounds i16, ptr %vecSrcB.0.in146, i32 32
180   %29 = tail call <8 x i16> @llvm.masked.load.v8i16.p0(ptr nonnull %add.ptr7, i32 2, <8 x i1> %28, <8 x i16> zeroinitializer)
181   %30 = tail call <8 x i16> @llvm.masked.load.v8i16.p0(ptr nonnull %add.ptr8, i32 2, <8 x i1> %28, <8 x i16> zeroinitializer)
182   %31 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.predicated.v8i16.v8i1(i32 0, i32 1, i32 0, i32 %accReal.1.off0, i32 %accReal.1.off32, <8 x i16> %29, <8 x i16> %30, <8 x i1> %28)
183   %32 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.predicated.v8i16.v8i1(i32 0, i32 0, i32 1, i32 %accImag.1.off0, i32 %accImag.1.off32, <8 x i16> %29, <8 x i16> %30, <8 x i1> %28)
184   %cmp10 = icmp ugt i32 %mul, 8
185   br i1 %cmp10, label %do.body.1, label %if.end.loopexit
187 do.body.1:                                        ; preds = %do.body
188   %sub9 = add nsw i32 %mul, -8
189   %accImag.1.off32.1 = extractvalue { i32, i32 } %32, 1
190   %accImag.1.off0.1 = extractvalue { i32, i32 } %32, 0
191   %accReal.1.off32.1 = extractvalue { i32, i32 } %31, 1
192   %accReal.1.off0.1 = extractvalue { i32, i32 } %31, 0
193   %33 = tail call <8 x i1> @llvm.arm.mve.vctp16(i32 %sub9)
194   %add.ptr7.1 = getelementptr inbounds i16, ptr %vecSrcA.0.in145, i32 40
195   %add.ptr8.1 = getelementptr inbounds i16, ptr %vecSrcB.0.in146, i32 40
196   %34 = tail call <8 x i16> @llvm.masked.load.v8i16.p0(ptr nonnull %add.ptr7.1, i32 2, <8 x i1> %33, <8 x i16> zeroinitializer)
197   %35 = tail call <8 x i16> @llvm.masked.load.v8i16.p0(ptr nonnull %add.ptr8.1, i32 2, <8 x i1> %33, <8 x i16> zeroinitializer)
198   %36 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.predicated.v8i16.v8i1(i32 0, i32 1, i32 0, i32 %accReal.1.off0.1, i32 %accReal.1.off32.1, <8 x i16> %34, <8 x i16> %35, <8 x i1> %33)
199   %37 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.predicated.v8i16.v8i1(i32 0, i32 0, i32 1, i32 %accImag.1.off0.1, i32 %accImag.1.off32.1, <8 x i16> %34, <8 x i16> %35, <8 x i1> %33)
200   br label %if.end.loopexit
202 if.else:                                          ; preds = %entry
203   %cmp13120.not = icmp eq i32 %numSamples, 0
204   br i1 %cmp13120.not, label %if.end, label %while.body14.preheader
206 while.body14.preheader:                           ; preds = %if.else
207   %mul11 = shl nuw nsw i32 %numSamples, 1
208   br label %while.body14
210 while.body14:                                     ; preds = %while.body14.preheader, %while.body14
211   %pSrcA.addr.2127 = phi ptr [ %add.ptr16, %while.body14 ], [ %pSrcA, %while.body14.preheader ]
212   %pSrcB.addr.2126 = phi ptr [ %add.ptr17, %while.body14 ], [ %pSrcB, %while.body14.preheader ]
213   %accImag.2.off32125 = phi i32 [ %45, %while.body14 ], [ 0, %while.body14.preheader ]
214   %accImag.2.off0124 = phi i32 [ %46, %while.body14 ], [ 0, %while.body14.preheader ]
215   %accReal.2.off32123 = phi i32 [ %42, %while.body14 ], [ 0, %while.body14.preheader ]
216   %accReal.2.off0122 = phi i32 [ %43, %while.body14 ], [ 0, %while.body14.preheader ]
217   %blkCnt.2121 = phi i32 [ %sub18, %while.body14 ], [ %mul11, %while.body14.preheader ]
218   %38 = tail call <8 x i1> @llvm.arm.mve.vctp16(i32 %blkCnt.2121)
219   %39 = tail call <8 x i16> @llvm.masked.load.v8i16.p0(ptr %pSrcA.addr.2127, i32 2, <8 x i1> %38, <8 x i16> zeroinitializer)
220   %40 = tail call <8 x i16> @llvm.masked.load.v8i16.p0(ptr %pSrcB.addr.2126, i32 2, <8 x i1> %38, <8 x i16> zeroinitializer)
221   %41 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.predicated.v8i16.v8i1(i32 0, i32 1, i32 0, i32 %accReal.2.off0122, i32 %accReal.2.off32123, <8 x i16> %39, <8 x i16> %40, <8 x i1> %38)
222   %42 = extractvalue { i32, i32 } %41, 1
223   %43 = extractvalue { i32, i32 } %41, 0
224   %44 = tail call { i32, i32 } @llvm.arm.mve.vmlldava.predicated.v8i16.v8i1(i32 0, i32 0, i32 1, i32 %accImag.2.off0124, i32 %accImag.2.off32125, <8 x i16> %39, <8 x i16> %40, <8 x i1> %38)
225   %45 = extractvalue { i32, i32 } %44, 1
226   %46 = extractvalue { i32, i32 } %44, 0
227   %add.ptr16 = getelementptr inbounds i16, ptr %pSrcA.addr.2127, i32 8
228   %add.ptr17 = getelementptr inbounds i16, ptr %pSrcB.addr.2126, i32 8
229   %sub18 = add nsw i32 %blkCnt.2121, -8
230   %cmp13 = icmp ugt i32 %blkCnt.2121, 8
231   br i1 %cmp13, label %while.body14, label %if.end.loopexit177
233 if.end.loopexit:                                  ; preds = %do.body.1, %do.body
234   %.lcssa200 = phi { i32, i32 } [ %31, %do.body ], [ %36, %do.body.1 ]
235   %.lcssa = phi { i32, i32 } [ %32, %do.body ], [ %37, %do.body.1 ]
236   %47 = extractvalue { i32, i32 } %.lcssa200, 1
237   %48 = extractvalue { i32, i32 } %.lcssa200, 0
238   %49 = extractvalue { i32, i32 } %.lcssa, 1
239   %50 = extractvalue { i32, i32 } %.lcssa, 0
240   br label %if.end
242 if.end.loopexit177:                               ; preds = %while.body14
243   %51 = extractvalue { i32, i32 } %41, 1
244   %52 = extractvalue { i32, i32 } %41, 0
245   %53 = extractvalue { i32, i32 } %44, 1
246   %54 = extractvalue { i32, i32 } %44, 0
247   br label %if.end
249 if.end:                                           ; preds = %if.end.loopexit177, %if.else, %if.end.loopexit
250   %accReal.3.off0 = phi i32 [ %48, %if.end.loopexit ], [ 0, %if.else ], [ %52, %if.end.loopexit177 ]
251   %accReal.3.off32 = phi i32 [ %47, %if.end.loopexit ], [ 0, %if.else ], [ %51, %if.end.loopexit177 ]
252   %accImag.3.off0 = phi i32 [ %50, %if.end.loopexit ], [ 0, %if.else ], [ %54, %if.end.loopexit177 ]
253   %accImag.3.off32 = phi i32 [ %49, %if.end.loopexit ], [ 0, %if.else ], [ %53, %if.end.loopexit177 ]
254   %55 = tail call { i32, i32 } @llvm.arm.mve.asrl(i32 %accReal.3.off0, i32 %accReal.3.off32, i32 6)
255   %56 = extractvalue { i32, i32 } %55, 0
256   store i32 %56, ptr %realResult, align 4
257   %57 = tail call { i32, i32 } @llvm.arm.mve.asrl(i32 %accImag.3.off0, i32 %accImag.3.off32, i32 6)
258   %58 = extractvalue { i32, i32 } %57, 0
259   store i32 %58, ptr %imagResult, align 4
260   ret void
263 declare { i32, i32 } @llvm.arm.mve.vmlldava.v8i16(i32, i32, i32, i32, i32, <8 x i16>, <8 x i16>) #1
264 declare <8 x i1> @llvm.arm.mve.vctp16(i32) #1
265 declare <8 x i16> @llvm.masked.load.v8i16.p0(ptr, i32 immarg, <8 x i1>, <8 x i16>) #2
266 declare { i32, i32 } @llvm.arm.mve.vmlldava.predicated.v8i16.v8i1(i32, i32, i32, i32, i32, <8 x i16>, <8 x i16>, <8 x i1>) #1
267 declare { i32, i32 } @llvm.arm.mve.asrl(i32, i32, i32) #1