1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=armv8.1m.main -mattr=+mve -tail-predication=enabled --verify-machineinstrs %s -o - | FileCheck %s
4 define void @arm_cmplx_mag_squared_q15_mve(ptr %pSrc, ptr %pDst, i32 %blockSize) {
5 ; CHECK-LABEL: arm_cmplx_mag_squared_q15_mve:
6 ; CHECK: @ %bb.0: @ %entry
7 ; CHECK-NEXT: push {r7, lr}
8 ; CHECK-NEXT: subs.w r3, r2, #8
9 ; CHECK-NEXT: dlstp.16 lr, r2
10 ; CHECK-NEXT: .LBB0_1: @ %do.body
11 ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
12 ; CHECK-NEXT: vld20.16 {q0, q1}, [r0]
13 ; CHECK-NEXT: vld21.16 {q0, q1}, [r0]!
14 ; CHECK-NEXT: vmulh.s16 q1, q1, q1
15 ; CHECK-NEXT: vmulh.s16 q0, q0, q0
16 ; CHECK-NEXT: vqadd.s16 q0, q0, q1
17 ; CHECK-NEXT: vshr.s16 q0, q0, #1
18 ; CHECK-NEXT: vstrh.16 q0, [r1], #16
19 ; CHECK-NEXT: letp lr, .LBB0_1
20 ; CHECK-NEXT: @ %bb.2: @ %do.end
21 ; CHECK-NEXT: pop {r7, pc}
25 do.body: ; preds = %do.body, %entry
26 %blockSize.addr.0 = phi i32 [ %blockSize, %entry ], [ %sub, %do.body ]
27 %pDst.addr.0 = phi ptr [ %pDst, %entry ], [ %add.ptr7, %do.body ]
28 %pSrc.addr.0 = phi ptr [ %pSrc, %entry ], [ %add.ptr, %do.body ]
29 %0 = tail call <8 x i1> @llvm.arm.mve.vctp16(i32 %blockSize.addr.0)
30 %1 = tail call { <8 x i16>, <8 x i16> } @llvm.arm.mve.vld2q.v8i16.p0(ptr %pSrc.addr.0)
31 %2 = extractvalue { <8 x i16>, <8 x i16> } %1, 0
32 %3 = extractvalue { <8 x i16>, <8 x i16> } %1, 1
33 %4 = tail call <8 x i16> @llvm.arm.mve.mulh.predicated.v8i16.v8i1(<8 x i16> %2, <8 x i16> %2, i32 0, <8 x i1> %0, <8 x i16> undef)
34 %5 = tail call <8 x i16> @llvm.arm.mve.mulh.predicated.v8i16.v8i1(<8 x i16> %3, <8 x i16> %3, i32 0, <8 x i1> %0, <8 x i16> undef)
35 %6 = tail call <8 x i16> @llvm.arm.mve.qadd.predicated.v8i16.v8i1(<8 x i16> %4, <8 x i16> %5, i32 0, <8 x i1> %0, <8 x i16> undef)
36 %7 = tail call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> %6, i32 1, i32 0, <8 x i1> %0, <8 x i16> undef)
37 %8 = bitcast ptr %pDst.addr.0 to ptr
38 tail call void @llvm.masked.store.v8i16.p0(<8 x i16> %7, ptr %8, i32 2, <8 x i1> %0)
39 %add.ptr = getelementptr inbounds i16, ptr %pSrc.addr.0, i32 16
40 %add.ptr7 = getelementptr inbounds i16, ptr %pDst.addr.0, i32 8
41 %sub = add i32 %blockSize.addr.0, -8
42 %cmp = icmp sgt i32 %sub, 0
43 br i1 %cmp, label %do.body, label %do.end
45 do.end: ; preds = %do.body
49 define i32 @bad(ptr readonly %x, ptr nocapture readonly %y, i32 %n) {
51 ; CHECK: @ %bb.0: @ %entry
52 ; CHECK-NEXT: push {r7, lr}
53 ; CHECK-NEXT: mov r3, r2
54 ; CHECK-NEXT: cmp r2, #4
56 ; CHECK-NEXT: movge r3, #4
57 ; CHECK-NEXT: subs r3, r2, r3
58 ; CHECK-NEXT: add.w r12, r3, #3
59 ; CHECK-NEXT: movs r3, #1
60 ; CHECK-NEXT: add.w r3, r3, r12, lsr #2
61 ; CHECK-NEXT: mov.w r12, #0
62 ; CHECK-NEXT: dls lr, r3
63 ; CHECK-NEXT: .LBB1_1: @ %do.body
64 ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
65 ; CHECK-NEXT: vctp.32 r2
66 ; CHECK-NEXT: vldrw.u32 q1, [r1], #16
68 ; CHECK-NEXT: vldrwt.u32 q0, [r0], #16
69 ; CHECK-NEXT: subs r2, #4
70 ; CHECK-NEXT: vmlava.s32 r12, q0, q1
71 ; CHECK-NEXT: le lr, .LBB1_1
72 ; CHECK-NEXT: @ %bb.2: @ %do.end
73 ; CHECK-NEXT: mov r0, r12
74 ; CHECK-NEXT: pop {r7, pc}
78 do.body: ; preds = %do.body, %entry
79 %s.0 = phi i32 [ 0, %entry ], [ %5, %do.body ]
80 %n.addr.0 = phi i32 [ %n, %entry ], [ %sub, %do.body ]
81 %y.addr.0 = phi ptr [ %y, %entry ], [ %add.ptr1, %do.body ]
82 %x.addr.0 = phi ptr [ %x, %entry ], [ %add.ptr, %do.body ]
83 %0 = tail call <4 x i1> @llvm.arm.mve.vctp32(i32 %n.addr.0)
84 %1 = bitcast ptr %x.addr.0 to ptr
85 %2 = tail call <4 x i32> @llvm.masked.load.v4i32.p0(ptr %1, i32 4, <4 x i1> %0, <4 x i32> zeroinitializer)
86 %add.ptr = getelementptr inbounds i32, ptr %x.addr.0, i32 4
87 %3 = bitcast ptr %y.addr.0 to ptr
88 %4 = load <4 x i32>, ptr %3, align 4
89 %add.ptr1 = getelementptr inbounds i32, ptr %y.addr.0, i32 4
90 %5 = tail call i32 @llvm.arm.mve.vmldava.v4i32(i32 0, i32 0, i32 0, i32 %s.0, <4 x i32> %2, <4 x i32> %4)
91 %sub = add nsw i32 %n.addr.0, -4
92 %cmp = icmp sgt i32 %n.addr.0, 4
93 br i1 %cmp, label %do.body, label %do.end
95 do.end: ; preds = %do.body
99 define i32 @good(ptr readonly %x, ptr readonly %y, i32 %n) {
101 ; CHECK: @ %bb.0: @ %entry
102 ; CHECK-NEXT: push {r7, lr}
103 ; CHECK-NEXT: mov.w r12, #0
104 ; CHECK-NEXT: dlstp.32 lr, r2
105 ; CHECK-NEXT: .LBB2_1: @ %do.body
106 ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
107 ; CHECK-NEXT: vldrw.u32 q0, [r1], #16
108 ; CHECK-NEXT: vldrw.u32 q1, [r0], #16
109 ; CHECK-NEXT: vmlava.s32 r12, q1, q0
110 ; CHECK-NEXT: letp lr, .LBB2_1
111 ; CHECK-NEXT: @ %bb.2: @ %do.end
112 ; CHECK-NEXT: mov r0, r12
113 ; CHECK-NEXT: pop {r7, pc}
117 do.body: ; preds = %do.body, %entry
118 %s.0 = phi i32 [ 0, %entry ], [ %5, %do.body ]
119 %n.addr.0 = phi i32 [ %n, %entry ], [ %sub, %do.body ]
120 %y.addr.0 = phi ptr [ %y, %entry ], [ %add.ptr1, %do.body ]
121 %x.addr.0 = phi ptr [ %x, %entry ], [ %add.ptr, %do.body ]
122 %0 = tail call <4 x i1> @llvm.arm.mve.vctp32(i32 %n.addr.0)
123 %1 = bitcast ptr %x.addr.0 to ptr
124 %2 = tail call <4 x i32> @llvm.masked.load.v4i32.p0(ptr %1, i32 4, <4 x i1> %0, <4 x i32> zeroinitializer)
125 %add.ptr = getelementptr inbounds i32, ptr %x.addr.0, i32 4
126 %3 = bitcast ptr %y.addr.0 to ptr
127 %4 = tail call <4 x i32> @llvm.masked.load.v4i32.p0(ptr %3, i32 4, <4 x i1> %0, <4 x i32> zeroinitializer)
128 %add.ptr1 = getelementptr inbounds i32, ptr %y.addr.0, i32 4
129 %5 = tail call i32 @llvm.arm.mve.vmldava.v4i32(i32 0, i32 0, i32 0, i32 %s.0, <4 x i32> %2, <4 x i32> %4)
130 %sub = add nsw i32 %n.addr.0, -4
131 %cmp = icmp sgt i32 %n.addr.0, 4
132 br i1 %cmp, label %do.body, label %do.end
134 do.end: ; preds = %do.body
138 define i32 @good2(ptr nocapture readonly %x, ptr nocapture readonly %y, i32 %n) {
139 ; CHECK-LABEL: good2:
140 ; CHECK: @ %bb.0: @ %entry
141 ; CHECK-NEXT: push {r7, lr}
142 ; CHECK-NEXT: mov.w r12, #0
143 ; CHECK-NEXT: dlstp.32 lr, r2
144 ; CHECK-NEXT: .LBB3_1: @ %do.body
145 ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
146 ; CHECK-NEXT: vldrw.u32 q0, [r1], #16
147 ; CHECK-NEXT: vldrw.u32 q1, [r0], #16
148 ; CHECK-NEXT: vmlava.s32 r12, q1, q0
149 ; CHECK-NEXT: letp lr, .LBB3_1
150 ; CHECK-NEXT: @ %bb.2: @ %do.end
151 ; CHECK-NEXT: mov r0, r12
152 ; CHECK-NEXT: pop {r7, pc}
156 do.body: ; preds = %do.body, %entry
157 %s.0 = phi i32 [ 0, %entry ], [ %5, %do.body ]
158 %n.addr.0 = phi i32 [ %n, %entry ], [ %sub, %do.body ]
159 %y.addr.0 = phi ptr [ %y, %entry ], [ %add.ptr1, %do.body ]
160 %x.addr.0 = phi ptr [ %x, %entry ], [ %add.ptr, %do.body ]
161 %0 = tail call <4 x i1> @llvm.arm.mve.vctp32(i32 %n.addr.0)
162 %1 = bitcast ptr %x.addr.0 to ptr
163 %2 = load <4 x i32>, ptr %1, align 4
164 %add.ptr = getelementptr inbounds i32, ptr %x.addr.0, i32 4
165 %3 = bitcast ptr %y.addr.0 to ptr
166 %4 = load <4 x i32>, ptr %3, align 4
167 %add.ptr1 = getelementptr inbounds i32, ptr %y.addr.0, i32 4
168 %5 = tail call i32 @llvm.arm.mve.vmldava.predicated.v4i32.v4i1(i32 0, i32 0, i32 0, i32 %s.0, <4 x i32> %2, <4 x i32> %4, <4 x i1> %0)
169 %sub = add nsw i32 %n.addr.0, -4
170 %cmp = icmp sgt i32 %n.addr.0, 4
171 br i1 %cmp, label %do.body, label %do.end
173 do.end: ; preds = %do.body
177 declare <8 x i1> @llvm.arm.mve.vctp16(i32)
178 declare { <8 x i16>, <8 x i16> } @llvm.arm.mve.vld2q.v8i16.p0(ptr)
179 declare <8 x i16> @llvm.arm.mve.mulh.predicated.v8i16.v8i1(<8 x i16>, <8 x i16>, i32, <8 x i1>, <8 x i16>)
180 declare <8 x i16> @llvm.arm.mve.qadd.predicated.v8i16.v8i1(<8 x i16>, <8 x i16>, i32, <8 x i1>, <8 x i16>)
181 declare <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16>, i32, i32, <8 x i1>, <8 x i16>)
182 declare void @llvm.masked.store.v8i16.p0(<8 x i16>, ptr, i32 immarg, <8 x i1>)
183 declare i32 @llvm.arm.mve.vmldava.predicated.v4i32.v4i1(i32, i32, i32, i32, <4 x i32>, <4 x i32>, <4 x i1>)
184 declare <4 x i1> @llvm.arm.mve.vctp32(i32) #1
185 declare <4 x i32> @llvm.masked.load.v4i32.p0(ptr, i32 immarg, <4 x i1>, <4 x i32>) #2
186 declare i32 @llvm.arm.mve.vmldava.v4i32(i32, i32, i32, i32, <4 x i32>, <4 x i32>) #1