xref: /llvm-project/llvm/test/Transforms/CodeGenPrepare/AArch64/reduce-or-opt.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -codegenprepare -S < %s -mtriple=aarch64-none-linux-gnu -mattr=+sve | FileCheck %s
3
4define i64 @select_or_reduce_v2i1(ptr nocapture noundef readonly %src) {
5; CHECK-LABEL: define i64 @select_or_reduce_v2i1(
6; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]]) #[[ATTR0:[0-9]+]] {
7; CHECK-NEXT:  [[ENTRY:.*]]:
8; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
9; CHECK:       [[VECTOR_BODY]]:
10; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
11; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]]
12; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x ptr>, ptr [[ARRAYIDX]], align 8
13; CHECK-NEXT:    [[COND:%.*]] = icmp eq <2 x ptr> [[WIDE_LOAD]], zeroinitializer
14; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
15; CHECK-NEXT:    [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[COND]])
16; CHECK-NEXT:    [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4
17; CHECK-NEXT:    [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]]
18; CHECK-NEXT:    br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]]
19; CHECK:       [[MIDDLE_SPLIT]]:
20; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[OR_REDUC]], i64 1, i64 0
21; CHECK-NEXT:    ret i64 [[SEL]]
22;
23entry:
24  br label %vector.body
25
26vector.body:
27  %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
28  %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index
29  %wide.load = load <2 x ptr>, ptr %arrayidx, align 8
30  %cond = icmp eq <2 x ptr> %wide.load, splat(ptr zeroinitializer)
31  %index.next = add nuw i64 %index, 2
32  %or.reduc = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> %cond)
33  %iv.cmp = icmp eq i64 %index.next, 4
34  %exit.cond = or i1 %or.reduc, %iv.cmp
35  br i1 %exit.cond, label %middle.split, label %vector.body
36
37middle.split:
38  %sel = select i1 %or.reduc, i64 1, i64 0
39  ret i64 %sel
40}
41
42define i64 @br_or_reduce_v2i1(ptr nocapture noundef readonly %src, ptr noundef readnone %p) {
43; CHECK-LABEL: define i64 @br_or_reduce_v2i1(
44; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]], ptr noundef readnone [[P:%.*]]) #[[ATTR0]] {
45; CHECK-NEXT:  [[ENTRY:.*]]:
46; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
47; CHECK:       [[VECTOR_BODY]]:
48; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
49; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]]
50; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x ptr>, ptr [[ARRAYIDX]], align 8
51; CHECK-NEXT:    [[COND:%.*]] = icmp eq <2 x ptr> [[WIDE_LOAD]], zeroinitializer
52; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
53; CHECK-NEXT:    [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[COND]])
54; CHECK-NEXT:    [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4
55; CHECK-NEXT:    [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]]
56; CHECK-NEXT:    br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]]
57; CHECK:       [[MIDDLE_SPLIT]]:
58; CHECK-NEXT:    br i1 [[OR_REDUC]], label %[[FOUND:.*]], label %[[NOTFOUND:.*]]
59; CHECK:       [[FOUND]]:
60; CHECK-NEXT:    store i64 56, ptr [[P]], align 8
61; CHECK-NEXT:    ret i64 1
62; CHECK:       [[NOTFOUND]]:
63; CHECK-NEXT:    ret i64 0
64;
65entry:
66  br label %vector.body
67
68vector.body:
69  %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
70  %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index
71  %wide.load = load <2 x ptr>, ptr %arrayidx, align 8
72  %cond = icmp eq <2 x ptr> %wide.load, splat(ptr zeroinitializer)
73  %index.next = add nuw i64 %index, 2
74  %or.reduc = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> %cond)
75  %iv.cmp = icmp eq i64 %index.next, 4
76  %exit.cond = or i1 %or.reduc, %iv.cmp
77  br i1 %exit.cond, label %middle.split, label %vector.body
78
79middle.split:
80  br i1 %or.reduc, label %found, label %notfound
81
82found:
83  store i64 56, ptr %p, align 8
84  ret i64 1
85
86notfound:
87  ret i64 0
88}
89
90define i64 @select_or_reduce_nxv2i1(ptr nocapture noundef readonly %src) {
91; CHECK-LABEL: define i64 @select_or_reduce_nxv2i1(
92; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]]) #[[ATTR0]] {
93; CHECK-NEXT:  [[ENTRY:.*]]:
94; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
95; CHECK:       [[VECTOR_BODY]]:
96; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
97; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]]
98; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <vscale x 2 x ptr>, ptr [[ARRAYIDX]], align 8
99; CHECK-NEXT:    [[COND:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer
100; CHECK-NEXT:    [[TMP0:%.*]] = tail call i64 @llvm.vscale.i64()
101; CHECK-NEXT:    [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 1
102; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]
103; CHECK-NEXT:    [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[COND]])
104; CHECK-NEXT:    [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4
105; CHECK-NEXT:    [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]]
106; CHECK-NEXT:    br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]]
107; CHECK:       [[MIDDLE_SPLIT]]:
108; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer
109; CHECK-NEXT:    [[TMP3:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[TMP2]])
110; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[TMP3]], i64 1, i64 0
111; CHECK-NEXT:    ret i64 [[SEL]]
112;
113entry:
114  %vscale = tail call i64 @llvm.vscale.i64()
115  %vf = shl nuw nsw i64 %vscale, 1
116  br label %vector.body
117
118vector.body:
119  %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
120  %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index
121  %wide.load = load <vscale x 2 x ptr>, ptr %arrayidx, align 8
122  %cond = icmp eq <vscale x 2 x ptr> %wide.load, splat(ptr zeroinitializer)
123  %index.next = add nuw i64 %index, %vf
124  %or.reduc = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> %cond)
125  %iv.cmp = icmp eq i64 %index.next, 4
126  %exit.cond = or i1 %or.reduc, %iv.cmp
127  br i1 %exit.cond, label %middle.split, label %vector.body
128
129middle.split:
130  %sel = select i1 %or.reduc, i64 1, i64 0
131  ret i64 %sel
132}
133
134define i64 @br_or_reduce_nxv2i1(ptr nocapture noundef readonly %src, ptr noundef readnone %p) {
135; CHECK-LABEL: define i64 @br_or_reduce_nxv2i1(
136; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]], ptr noundef readnone [[P:%.*]]) #[[ATTR0]] {
137; CHECK-NEXT:  [[ENTRY:.*]]:
138; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
139; CHECK:       [[VECTOR_BODY]]:
140; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
141; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]]
142; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <vscale x 2 x ptr>, ptr [[ARRAYIDX]], align 8
143; CHECK-NEXT:    [[COND:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer
144; CHECK-NEXT:    [[TMP0:%.*]] = tail call i64 @llvm.vscale.i64()
145; CHECK-NEXT:    [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 1
146; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]]
147; CHECK-NEXT:    [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[COND]])
148; CHECK-NEXT:    [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4
149; CHECK-NEXT:    [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]]
150; CHECK-NEXT:    br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]]
151; CHECK:       [[MIDDLE_SPLIT]]:
152; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer
153; CHECK-NEXT:    [[TMP3:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[TMP2]])
154; CHECK-NEXT:    br i1 [[TMP3]], label %[[FOUND:.*]], label %[[NOTFOUND:.*]]
155; CHECK:       [[FOUND]]:
156; CHECK-NEXT:    store i64 56, ptr [[P]], align 8
157; CHECK-NEXT:    ret i64 1
158; CHECK:       [[NOTFOUND]]:
159; CHECK-NEXT:    ret i64 0
160;
161entry:
162  %vscale = tail call i64 @llvm.vscale.i64()
163  %vf = shl nuw nsw i64 %vscale, 1
164  br label %vector.body
165
166vector.body:
167  %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
168  %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index
169  %wide.load = load <vscale x 2 x ptr>, ptr %arrayidx, align 8
170  %cond = icmp eq <vscale x 2 x ptr> %wide.load, splat(ptr zeroinitializer)
171  %index.next = add nuw i64 %index, %vf
172  %or.reduc = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> %cond)
173  %iv.cmp = icmp eq i64 %index.next, 4
174  %exit.cond = or i1 %or.reduc, %iv.cmp
175  br i1 %exit.cond, label %middle.split, label %vector.body
176
177middle.split:
178  br i1 %or.reduc, label %found, label %notfound
179
180found:
181  store i64 56, ptr %p, align 8
182  ret i64 1
183
184notfound:
185  ret i64 0
186}
187
188declare i1 @llvm.vector.reduce.or.v2i1(<2 x i1>)
189declare i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1>)
190