xref: /llvm-project/llvm/test/CodeGen/LoongArch/bstrins_w.ll (revision 9d4f7f44b64d87d1068859906f43b7ce03a7388b)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s
3
4;; Test generation of the bstrins.w instruction.
5;; There are 8 patterns that can be matched to bstrins.w. See performORCombine
6;; for details.
7
8;; Pattern 1
9;; R = or (and X, mask0), (and (shl Y, lsb), mask1)
10;; =>
11;; R = BSTRINS X, Y, msb, lsb
12define i32 @pat1(i32 %a, i32 %b) nounwind {
13; CHECK-LABEL: pat1:
14; CHECK:       # %bb.0:
15; CHECK-NEXT:    bstrins.w $a0, $a1, 19, 8
16; CHECK-NEXT:    ret
17  %and1 = and i32 %a, -1048321  ; 0xfff000ff
18  %shl = shl i32 %b, 8
19  %and2 = and i32 %shl, 1048320 ; 0x000fff00
20  %or = or i32 %and1, %and2
21  ret i32 %or
22}
23
24define i32 @pat1_swap(i32 %a, i32 %b) nounwind {
25; CHECK-LABEL: pat1_swap:
26; CHECK:       # %bb.0:
27; CHECK-NEXT:    bstrins.w $a0, $a1, 19, 8
28; CHECK-NEXT:    ret
29  %and1 = and i32 %a, -1048321  ; 0xfff000ff
30  %shl = shl i32 %b, 8
31  %and2 = and i32 %shl, 1048320 ; 0x000fff00
32  %or = or i32 %and2, %and1
33  ret i32 %or
34}
35
36;; Pattern 2
37;; R = or (and X, mask0), (shl (and Y, mask1), lsb)
38;; =>
39;; R = BSTRINS X, Y, msb, lsb
40define i32 @pat2(i32 %a, i32 %b) nounwind {
41; CHECK-LABEL: pat2:
42; CHECK:       # %bb.0:
43; CHECK-NEXT:    bstrins.w $a0, $a1, 19, 8
44; CHECK-NEXT:    ret
45  %and1 = and i32 %a, -1048321 ; 0xfff000ff
46  %and2 = and i32 %b, 4095     ; 0x00000fff
47  %shl = shl i32 %and2, 8
48  %or = or i32 %and1, %shl
49  ret i32 %or
50}
51
52define i32 @pat2_swap(i32 %a, i32 %b) nounwind {
53; CHECK-LABEL: pat2_swap:
54; CHECK:       # %bb.0:
55; CHECK-NEXT:    bstrins.w $a0, $a1, 19, 8
56; CHECK-NEXT:    ret
57  %and1 = and i32 %a, -1048321 ; 0xfff000ff
58  %and2 = and i32 %b, 4095     ; 0x00000fff
59  %shl = shl i32 %and2, 8
60  %or = or i32 %shl, %and1
61  ret i32 %or
62}
63
64;; Pattern 3
65;; R = or (and X, mask0), (and Y, mask1)
66;; =>
67;; R = BSTRINS X, (srl (and Y, mask1), lsb), msb, lsb
68define i32 @pat3(i32 %a, i32 %b) nounwind {
69; CHECK-LABEL: pat3:
70; CHECK:       # %bb.0:
71; CHECK-NEXT:    andi $a1, $a1, 288
72; CHECK-NEXT:    srli.w $a1, $a1, 4
73; CHECK-NEXT:    bstrins.w $a0, $a1, 11, 4
74; CHECK-NEXT:    ret
75  %and1 = and i32 %a, -4081 ; 0xfffff00f
76  %and2 = and i32 %b, 288   ; 0x00000120
77  %or = or i32 %and1, %and2
78  ret i32 %or
79}
80
81define i32 @pat3_swap(i32 %a, i32 %b) nounwind {
82; CHECK-LABEL: pat3_swap:
83; CHECK:       # %bb.0:
84; CHECK-NEXT:    andi $a1, $a1, 288
85; CHECK-NEXT:    srli.w $a1, $a1, 4
86; CHECK-NEXT:    bstrins.w $a0, $a1, 11, 4
87; CHECK-NEXT:    ret
88  %and1 = and i32 %a, -4081 ; 0xfffff00f
89  %and2 = and i32 %b, 288   ; 0x00000120
90  %or = or i32 %and2, %and1
91  ret i32 %or
92}
93
94define i32 @pat3_positive_mask0(i32 %a, i32 %b) nounwind {
95; CHECK-LABEL: pat3_positive_mask0:
96; CHECK:       # %bb.0:
97; CHECK-NEXT:    srli.w $a1, $a1, 28
98; CHECK-NEXT:    bstrins.w $a0, $a1, 31, 28
99; CHECK-NEXT:    ret
100  %and1 = and i32 %a, 268435455  ; 0x0fffffff
101  %and2 = and i32 %b, 4026531840 ; 0xf0000000
102  %or = or i32 %and1, %and2
103  ret i32 %or
104}
105
106;; Pattern 4
107;; R = or (and X, mask), (shl Y, shamt)
108;; =>
109;; R = BSTRINS X, Y, 31, shamt
110define i32 @pat4(i32 %a, i32 %b) nounwind {
111; CHECK-LABEL: pat4:
112; CHECK:       # %bb.0:
113; CHECK-NEXT:    bstrins.w $a0, $a1, 31, 28
114; CHECK-NEXT:    ret
115  %and = and i32 %a, 268435455 ; 0x0fffffff
116  %shl = shl i32 %b, 28
117  %or = or i32 %and, %shl
118  ret i32 %or
119}
120
121define i32 @pat4_swap(i32 %a, i32 %b) nounwind {
122; CHECK-LABEL: pat4_swap:
123; CHECK:       # %bb.0:
124; CHECK-NEXT:    bstrins.w $a0, $a1, 31, 28
125; CHECK-NEXT:    ret
126  %and = and i32 %a, 268435455 ; 0x0fffffff
127  %shl = shl i32 %b, 28
128  %or = or i32 %shl, %and
129  ret i32 %or
130}
131
132;; Pattern 5
133;; R = or (and X, mask), const
134;; =>
135;; R = BSTRINS X, (const >> lsb), msb, lsb
136define i32 @pat5(i32 %a) nounwind {
137; CHECK-LABEL: pat5:
138; CHECK:       # %bb.0:
139; CHECK-NEXT:    lu12i.w $a1, 1
140; CHECK-NEXT:    ori $a1, $a1, 564
141; CHECK-NEXT:    bstrins.w $a0, $a1, 23, 8
142; CHECK-NEXT:    ret
143  %and = and i32 %a, 4278190335 ; 0xff0000ff
144  %or = or i32 %and, 1192960    ; 0x00123400
145  ret i32 %or
146}
147
148;; The high bits of `const` are zero.
149define i32 @pat5_high_zeros(i32 %a) nounwind {
150; CHECK-LABEL: pat5_high_zeros:
151; CHECK:       # %bb.0:
152; CHECK-NEXT:    lu12i.w $a1, 1
153; CHECK-NEXT:    ori $a1, $a1, 564
154; CHECK-NEXT:    bstrins.w $a0, $a1, 31, 16
155; CHECK-NEXT:    ret
156  %and = and i32 %a, 65535      ; 0x0000ffff
157  %or = or i32 %and, 305397760  ; 0x12340000
158  ret i32 %or
159}
160
161;; Pattern 6: a = b | ((c & mask) << shamt)
162;; In this testcase b is 0x10000002, but in fact we do not require b being a
163;; constant. As long as all positions in b to be overwritten by the incoming
164;; bits are known to be zero, the pattern could be matched.
165define i32 @pat6(i32 %c) nounwind {
166; CHECK-LABEL: pat6:
167; CHECK:       # %bb.0:
168; CHECK-NEXT:    lu12i.w $a1, 65536
169; CHECK-NEXT:    ori $a1, $a1, 2
170; CHECK-NEXT:    bstrins.w $a1, $a0, 27, 4
171; CHECK-NEXT:    move $a0, $a1
172; CHECK-NEXT:    ret
173  %and = and i32 %c, 16777215  ; 0x00ffffff
174  %shl = shl i32 %and, 4
175  %or = or i32 %shl, 268435458 ; 0x10000002
176  ret i32 %or
177}
178
179;; Pattern 7: a = b | ((c << shamt) & shifted_mask)
180;; Similar to pattern 6.
181define i32 @pat7(i32 %c) nounwind {
182; CHECK-LABEL: pat7:
183; CHECK:       # %bb.0:
184; CHECK-NEXT:    lu12i.w $a1, 65536
185; CHECK-NEXT:    ori $a1, $a1, 2
186; CHECK-NEXT:    bstrins.w $a1, $a0, 27, 4
187; CHECK-NEXT:    move $a0, $a1
188; CHECK-NEXT:    ret
189  %shl = shl i32 %c, 4
190  %and = and i32 %shl, 268435440 ; 0x0ffffff0
191  %or = or i32 %and, 268435458   ; 0x10000002
192  ret i32 %or
193}
194
195;; Pattern 8: a = b | (c & shifted_mask)
196;; Similar to pattern 7 but without shift to c.
197define i32 @pat8(i32 %c) nounwind {
198; CHECK-LABEL: pat8:
199; CHECK:       # %bb.0:
200; CHECK-NEXT:    srli.w $a1, $a0, 4
201; CHECK-NEXT:    lu12i.w $a0, 65536
202; CHECK-NEXT:    ori $a0, $a0, 2
203; CHECK-NEXT:    bstrins.w $a0, $a1, 27, 4
204; CHECK-NEXT:    ret
205  %and = and i32 %c, 268435440 ; 0x0ffffff0
206  %or = or i32 %and, 268435458 ; 0x10000002
207  ret i32 %or
208}
209
210;; Test that bstrins.w is not generated because constant OR operand
211;; doesn't fit into bits cleared by constant AND operand.
212define i32 @no_bstrins_w(i32 %a) nounwind {
213; CHECK-LABEL: no_bstrins_w:
214; CHECK:       # %bb.0:
215; CHECK-NEXT:    lu12i.w $a1, 291
216; CHECK-NEXT:    ori $a1, $a1, 1104
217; CHECK-NEXT:    or $a0, $a0, $a1
218; CHECK-NEXT:    lu12i.w $a1, -3805
219; CHECK-NEXT:    ori $a1, $a1, 1279
220; CHECK-NEXT:    and $a0, $a0, $a1
221; CHECK-NEXT:    ret
222  %and = and i32 %a, 4278190335 ; 0xff0000ff
223  %or = or i32 %and, 1193040    ; 0x00123450
224  ret i32 %or
225}
226