[OpenMP][Flang] Workaround omp_lib error (#123666)
[llvm-project.git] / llvm / test / CodeGen / AArch64 / aarch64-split-and-bitmask-immediate.ll
blobe31c9a072dc4b5f251ff729086ee36e88781abc0
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s
4 define i8 @test1(i32 %a) {
5 ; CHECK-LABEL: test1:
6 ; CHECK:       // %bb.0: // %entry
7 ; CHECK-NEXT:    and w8, w0, #0x3ffc00
8 ; CHECK-NEXT:    and w8, w8, #0xffe007ff
9 ; CHECK-NEXT:    cmp w8, #1024
10 ; CHECK-NEXT:    cset w0, eq
11 ; CHECK-NEXT:    ret
12 entry:
13   %and = and i32 %a, 2098176
14   %cmp = icmp eq i32 %and, 1024
15   %conv = zext i1 %cmp to i8
16   ret i8 %conv
19 ; This constant should not be split because it can be handled by one mov.
20 define i8 @test2(i32 %a) {
21 ; CHECK-LABEL: test2:
22 ; CHECK:       // %bb.0: // %entry
23 ; CHECK-NEXT:    mov w8, #135 // =0x87
24 ; CHECK-NEXT:    and w8, w0, w8
25 ; CHECK-NEXT:    cmp w8, #1024
26 ; CHECK-NEXT:    cset w0, eq
27 ; CHECK-NEXT:    ret
28 entry:
29   %and = and i32 %a, 135
30   %cmp = icmp eq i32 %and, 1024
31   %conv = zext i1 %cmp to i8
32   ret i8 %conv
35 ; This constant should not be split because the split immediate is not valid
36 ; bitmask immediate.
37 define i8 @test3(i32 %a) {
38 ; CHECK-LABEL: test3:
39 ; CHECK:       // %bb.0: // %entry
40 ; CHECK-NEXT:    mov w8, #1024 // =0x400
41 ; CHECK-NEXT:    movk w8, #33, lsl #16
42 ; CHECK-NEXT:    and w8, w0, w8
43 ; CHECK-NEXT:    cmp w8, #1024
44 ; CHECK-NEXT:    cset w0, eq
45 ; CHECK-NEXT:    ret
46 entry:
47   %and = and i32 %a, 2163712
48   %cmp = icmp eq i32 %and, 1024
49   %conv = zext i1 %cmp to i8
50   ret i8 %conv
53 define i8 @test4(i64 %a) {
54 ; CHECK-LABEL: test4:
55 ; CHECK:       // %bb.0: // %entry
56 ; CHECK-NEXT:    and x8, x0, #0x3ffc00
57 ; CHECK-NEXT:    and x8, x8, #0xffffffffffe007ff
58 ; CHECK-NEXT:    cmp x8, #1024
59 ; CHECK-NEXT:    cset w0, eq
60 ; CHECK-NEXT:    ret
61 entry:
62   %and = and i64 %a, 2098176
63   %cmp = icmp eq i64 %and, 1024
64   %conv = zext i1 %cmp to i8
65   ret i8 %conv
68 define i8 @test5(i64 %a) {
69 ; CHECK-LABEL: test5:
70 ; CHECK:       // %bb.0: // %entry
71 ; CHECK-NEXT:    and x8, x0, #0x3ffffc000
72 ; CHECK-NEXT:    and x8, x8, #0xfffffffe00007fff
73 ; CHECK-NEXT:    cmp x8, #1024
74 ; CHECK-NEXT:    cset w0, eq
75 ; CHECK-NEXT:    ret
76 entry:
77   %and = and i64 %a, 8589950976
78   %cmp = icmp eq i64 %and, 1024
79   %conv = zext i1 %cmp to i8
80   ret i8 %conv
83 ; This constant should not be split because it can be handled by one mov.
84 define i8 @test6(i64 %a) {
85 ; CHECK-LABEL: test6:
86 ; CHECK:       // %bb.0: // %entry
87 ; CHECK-NEXT:    mov w8, #135 // =0x87
88 ; CHECK-NEXT:    and x8, x0, x8
89 ; CHECK-NEXT:    cmp x8, #1024
90 ; CHECK-NEXT:    cset w0, eq
91 ; CHECK-NEXT:    ret
92 entry:
93   %and = and i64 %a, 135
94   %cmp = icmp eq i64 %and, 1024
95   %conv = zext i1 %cmp to i8
96   ret i8 %conv
99 ; This constant should not be split because the split immediate is not valid
100 ; bitmask immediate.
101 define i8 @test7(i64 %a) {
102 ; CHECK-LABEL: test7:
103 ; CHECK:       // %bb.0: // %entry
104 ; CHECK-NEXT:    mov w8, #1024 // =0x400
105 ; CHECK-NEXT:    movk w8, #33, lsl #16
106 ; CHECK-NEXT:    and x8, x0, x8
107 ; CHECK-NEXT:    cmp x8, #1024
108 ; CHECK-NEXT:    cset w0, eq
109 ; CHECK-NEXT:    ret
110 entry:
111   %and = and i64 %a, 2163712
112   %cmp = icmp eq i64 %and, 1024
113   %conv = zext i1 %cmp to i8
114   ret i8 %conv
117 ; The split bitmask immediates should be hoisted outside loop because they are
118 ; loop invariant.
119 define void @test8(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
120 ; CHECK-LABEL: test8:
121 ; CHECK:       // %bb.0: // %loop.ph
122 ; CHECK-NEXT:    and x9, x0, #0x3ffc00
123 ; CHECK-NEXT:    mov x8, xzr
124 ; CHECK-NEXT:    and x9, x9, #0xffffffffffe007ff
125 ; CHECK-NEXT:    b .LBB7_2
126 ; CHECK-NEXT:  .LBB7_1: // %for.inc
127 ; CHECK-NEXT:    // in Loop: Header=BB7_2 Depth=1
128 ; CHECK-NEXT:    add x8, x8, #1
129 ; CHECK-NEXT:    cmp x8, x3
130 ; CHECK-NEXT:    b.gt .LBB7_4
131 ; CHECK-NEXT:  .LBB7_2: // %loop
132 ; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
133 ; CHECK-NEXT:    cmp x8, x9
134 ; CHECK-NEXT:    b.hs .LBB7_1
135 ; CHECK-NEXT:  // %bb.3: // %if.then
136 ; CHECK-NEXT:    // in Loop: Header=BB7_2 Depth=1
137 ; CHECK-NEXT:    ldr x10, [x1, x8, lsl #3]
138 ; CHECK-NEXT:    str x10, [x2, x8, lsl #3]
139 ; CHECK-NEXT:    b .LBB7_1
140 ; CHECK-NEXT:  .LBB7_4: // %exit
141 ; CHECK-NEXT:    ret
142 loop.ph:
143   br label %loop
145 loop:
146   %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
147   %and = and i64 %a, 2098176
148   %cmp = icmp ult i64 %iv, %and
149   br i1 %cmp, label %if.then, label %if.else
151 if.then:
152   %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
153   %val = load i64, ptr %src.arrayidx
154   %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
155   store i64 %val, ptr %dst.arrayidx
156   br label %for.inc
158 if.else:
159   br label %for.inc
161 for.inc:
162   %inc = add nuw nsw i64 %iv, 1
163   %cond = icmp sgt i64 %inc, %n
164   br i1 %cond, label %exit, label %loop
166 exit:
167   ret void
170 ; This constant should not be split because the `and` is not loop invariant.
171 define i32 @test9(ptr nocapture %x, ptr nocapture readonly %y, i32 %n) {
172 ; CHECK-LABEL: test9:
173 ; CHECK:       // %bb.0: // %entry
174 ; CHECK-NEXT:    cmp w2, #1
175 ; CHECK-NEXT:    b.lt .LBB8_3
176 ; CHECK-NEXT:  // %bb.1: // %for.body.preheader
177 ; CHECK-NEXT:    mov w9, #1024 // =0x400
178 ; CHECK-NEXT:    mov w8, w2
179 ; CHECK-NEXT:    movk w9, #32, lsl #16
180 ; CHECK-NEXT:  .LBB8_2: // %for.body
181 ; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
182 ; CHECK-NEXT:    ldr w10, [x1], #4
183 ; CHECK-NEXT:    subs x8, x8, #1
184 ; CHECK-NEXT:    and w10, w10, w9
185 ; CHECK-NEXT:    str w10, [x0], #4
186 ; CHECK-NEXT:    b.ne .LBB8_2
187 ; CHECK-NEXT:  .LBB8_3: // %for.cond.cleanup
188 ; CHECK-NEXT:    mov w0, wzr
189 ; CHECK-NEXT:    ret
190 entry:
191   %cmp8 = icmp sgt i32 %n, 0
192   br i1 %cmp8, label %for.body.preheader, label %for.cond.cleanup
194 for.body.preheader:                               ; preds = %entry
195   %wide.trip.count = zext i32 %n to i64
196   br label %for.body
198 for.cond.cleanup:                                 ; preds = %for.body, %entry
199   ret i32 0
201 for.body:                                         ; preds = %for.body.preheader, %for.body
202   %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
203   %arrayidx = getelementptr inbounds i32, ptr %y, i64 %indvars.iv
204   %0 = load i32, ptr %arrayidx, align 4
205   %and = and i32 %0, 2098176
206   %arrayidx2 = getelementptr inbounds i32, ptr %x, i64 %indvars.iv
207   store i32 %and, ptr %arrayidx2, align 4
208   %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
209   %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count
210   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
213 ; After instruction selection end, we can see the `and` and `or` share the
214 ; constant as below.
216 ; %4:gpr32 = MOVi32imm 2098176
217 ; %5:gpr32 = ANDWrr killed %3:gpr32, %4:gpr32
218 ; STRWui killed %5:gpr32, %0:gpr64common, 0 :: (store (s32) into %ir.x, !tbaa !8)
219 ; %6:gpr32 = LDRWui %1:gpr64common, 0 :: (load (s32) from %ir.y, !tbaa !8)
220 ; %7:gpr32 = ORRWrr killed %6:gpr32, %4:gpr32
222 ; In this case, the constant should not be split because it causes more
223 ; instructions.
224 define void @test10(ptr nocapture %x, ptr nocapture readonly %y, ptr nocapture %z) {
225 ; CHECK-LABEL: test10:
226 ; CHECK:       // %bb.0: // %entry
227 ; CHECK-NEXT:    ldr w8, [x1]
228 ; CHECK-NEXT:    mov w9, #1024 // =0x400
229 ; CHECK-NEXT:    movk w9, #32, lsl #16
230 ; CHECK-NEXT:    and w8, w8, w9
231 ; CHECK-NEXT:    str w8, [x0]
232 ; CHECK-NEXT:    ldr w8, [x1]
233 ; CHECK-NEXT:    orr w8, w8, w9
234 ; CHECK-NEXT:    str w8, [x2]
235 ; CHECK-NEXT:    ret
236 entry:
237   %0 = load i32, ptr %y, align 4
238   %and = and i32 %0, 2098176
239   store i32 %and, ptr %x, align 4
240   %1 = load i32, ptr %y, align 4
241   %or = or i32 %1, 2098176
242   store i32 %or, ptr %z, align 4
243   ret void
246 ; This test genereates below MIs.
248 ; MOVi32imm -1610612736
249 ; SUBREG_TO_REG
251 ; The constant should be zero-extended to 64 bit and it should not be split.
252 define i8 @test11(i64 %a) {
253 ; CHECK-LABEL: test11:
254 ; CHECK:       // %bb.0: // %entry
255 ; CHECK-NEXT:    mov w8, #-1610612736 // =0xa0000000
256 ; CHECK-NEXT:    and x8, x0, x8
257 ; CHECK-NEXT:    cmp x8, #1024
258 ; CHECK-NEXT:    cset w0, eq
259 ; CHECK-NEXT:    ret
260 entry:
261   %and = and i64 %a, 2684354560
262   %cmp = icmp eq i64 %and, 1024
263   %conv = zext i1 %cmp to i8
264   ret i8 %conv