xref: /llvm-project/llvm/test/CodeGen/LoongArch/bstrins_d.ll (revision 9d4f7f44b64d87d1068859906f43b7ce03a7388b)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s
3
4;; Test generation of the bstrins.d instruction.
5;; There are 8 patterns that can be matched to bstrins.d. 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 i64 @pat1(i64 %a, i64 %b) nounwind {
13; CHECK-LABEL: pat1:
14; CHECK:       # %bb.0:
15; CHECK-NEXT:    bstrins.d $a0, $a1, 39, 16
16; CHECK-NEXT:    ret
17  %and1 = and i64 %a, -1099511562241  ; 0xffffff000000ffff
18  %shl = shl i64 %b, 16
19  %and2 = and i64 %shl, 1099511562240 ; 0x000000ffffff0000
20  %or = or i64 %and1, %and2
21  ret i64 %or
22}
23
24define i64 @pat1_swap(i64 %a, i64 %b) nounwind {
25; CHECK-LABEL: pat1_swap:
26; CHECK:       # %bb.0:
27; CHECK-NEXT:    bstrins.d $a0, $a1, 39, 16
28; CHECK-NEXT:    ret
29  %and1 = and i64 %a, -1099511562241  ; 0xffffff000000ffff
30  %shl = shl i64 %b, 16
31  %and2 = and i64 %shl, 1099511562240 ; 0x000000ffffff0000
32  %or = or i64 %and2, %and1
33  ret i64 %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 i64 @pat2(i64 %a, i64 %b) nounwind {
41; CHECK-LABEL: pat2:
42; CHECK:       # %bb.0:
43; CHECK-NEXT:    bstrins.d $a0, $a1, 39, 16
44; CHECK-NEXT:    ret
45  %and1 = and i64 %a, -1099511562241 ; 0xffffff000000ffff
46  %and2 = and i64 %b, 16777215       ; 0x0000000000ffffff
47  %shl = shl i64 %and2, 16
48  %or = or i64 %and1, %shl
49  ret i64 %or
50}
51
52define i64 @pat2_swap(i64 %a, i64 %b) nounwind {
53; CHECK-LABEL: pat2_swap:
54; CHECK:       # %bb.0:
55; CHECK-NEXT:    bstrins.d $a0, $a1, 39, 16
56; CHECK-NEXT:    ret
57  %and1 = and i64 %a, -1099511562241 ; 0xffffff000000ffff
58  %and2 = and i64 %b, 16777215       ; 0x0000000000ffffff
59  %shl = shl i64 %and2, 16
60  %or = or i64 %shl, %and1
61  ret i64 %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 i64 @pat3(i64 %a, i64 %b) nounwind {
69; CHECK-LABEL: pat3:
70; CHECK:       # %bb.0:
71; CHECK-NEXT:    andi $a1, $a1, 288
72; CHECK-NEXT:    srli.d $a1, $a1, 4
73; CHECK-NEXT:    bstrins.d $a0, $a1, 11, 4
74; CHECK-NEXT:    ret
75  %and1 = and i64 %a, -4081 ; 0xfffffffffffff00f
76  %and2 = and i64 %b, 288   ; 0x0000000000000120
77  %or = or i64 %and1, %and2
78  ret i64 %or
79}
80
81define i64 @pat3_swap(i64 %a, i64 %b) nounwind {
82; CHECK-LABEL: pat3_swap:
83; CHECK:       # %bb.0:
84; CHECK-NEXT:    andi $a1, $a1, 288
85; CHECK-NEXT:    srli.d $a1, $a1, 4
86; CHECK-NEXT:    bstrins.d $a0, $a1, 11, 4
87; CHECK-NEXT:    ret
88  %and1 = and i64 %a, -4081 ; 0xfffffffffffff00f
89  %and2 = and i64 %b, 288   ; 0x0000000000000120
90  %or = or i64 %and2, %and1
91  ret i64 %or
92}
93
94;; Pattern 4
95;; R = or (and X, mask), (shl Y, shamt)
96;; =>
97;; R = BSTRINS X, Y, 63, shamt
98define i64 @pat4(i64 %a, i64 %b) nounwind {
99; CHECK-LABEL: pat4:
100; CHECK:       # %bb.0:
101; CHECK-NEXT:    bstrins.d $a0, $a1, 63, 8
102; CHECK-NEXT:    ret
103  %and = and i64 %a, 255
104  %shl = shl i64 %b, 8
105  %or = or i64 %and, %shl
106  ret i64 %or
107}
108
109define i64 @pat4_swap(i64 %a, i64 %b) nounwind {
110; CHECK-LABEL: pat4_swap:
111; CHECK:       # %bb.0:
112; CHECK-NEXT:    bstrins.d $a0, $a1, 63, 8
113; CHECK-NEXT:    ret
114  %and = and i64 %a, 255
115  %shl = shl i64 %b, 8
116  %or = or i64 %shl, %and
117  ret i64 %or
118}
119
120;; Pattern 5
121;; R = or (and X, mask0), const
122;; =>
123;; R = BSTRINS X, (const >> lsb), msb, lsb
124define i64 @pat5(i64 %a) nounwind {
125; CHECK-LABEL: pat5:
126; CHECK:       # %bb.0:
127; CHECK-NEXT:    lu12i.w $a1, 74565
128; CHECK-NEXT:    ori $a1, $a1, 1656
129; CHECK-NEXT:    bstrins.d $a0, $a1, 47, 16
130; CHECK-NEXT:    ret
131  %and = and i64 %a, 18446462598732906495 ; 0xffff00000000ffff
132  %or = or i64 %and, 20015998304256       ; 0x0000123456780000
133  ret i64 %or
134}
135
136;; Pattern 6: a = b | ((c & mask) << shamt)
137;; In this testcase b is 0x123456000000789a, but in fact we do not require b
138;; being a constant. As long as all positions in b to be overwritten by the
139;; incoming bits are known to be zero, the pattern could be matched.
140define i64 @pat6(i64 %c) nounwind {
141; CHECK-LABEL: pat6:
142; CHECK:       # %bb.0:
143; CHECK-NEXT:    lu12i.w $a1, 7
144; CHECK-NEXT:    ori $a1, $a1, 2202
145; CHECK-NEXT:    lu32i.d $a1, 284160
146; CHECK-NEXT:    lu52i.d $a1, $a1, 291
147; CHECK-NEXT:    bstrins.d $a1, $a0, 39, 16
148; CHECK-NEXT:    move $a0, $a1
149; CHECK-NEXT:    ret
150  %and = and i64 %c, 16777215            ; 0x0000000000ffffff
151  %shl = shl i64 %and, 16
152  %or = or i64 %shl, 1311767949471676570 ; 0x123456000000789a
153  ret i64 %or
154}
155
156;; Pattern 7: a = b | ((c << shamt) & shifted_mask)
157;; Similar to pattern 6.
158define i64 @pat7(i64 %c) nounwind {
159; CHECK-LABEL: pat7:
160; CHECK:       # %bb.0:
161; CHECK-NEXT:    lu12i.w $a1, 7
162; CHECK-NEXT:    ori $a1, $a1, 2202
163; CHECK-NEXT:    lu32i.d $a1, 284160
164; CHECK-NEXT:    lu52i.d $a1, $a1, 291
165; CHECK-NEXT:    bstrins.d $a1, $a0, 39, 16
166; CHECK-NEXT:    move $a0, $a1
167; CHECK-NEXT:    ret
168  %shl = shl i64 %c, 16
169  %and = and i64 %shl, 1099511562240     ; 0x000000ffffff0000
170  %or = or i64 %and, 1311767949471676570 ; 0x123456000000789a
171  ret i64 %or
172}
173
174;; Pattern 8: a = b | (c & shifted_mask)
175;; Similar to pattern 7 but without shift to c.
176define i64 @pat8(i64 %c) nounwind {
177; CHECK-LABEL: pat8:
178; CHECK:       # %bb.0:
179; CHECK-NEXT:    srli.d $a1, $a0, 16
180; CHECK-NEXT:    lu12i.w $a0, 7
181; CHECK-NEXT:    ori $a0, $a0, 2202
182; CHECK-NEXT:    lu32i.d $a0, 284160
183; CHECK-NEXT:    lu52i.d $a0, $a0, 291
184; CHECK-NEXT:    bstrins.d $a0, $a1, 39, 16
185; CHECK-NEXT:    ret
186  %and = and i64 %c, 1099511562240       ; 0x000000ffffff0000
187  %or = or i64 %and, 1311767949471676570 ; 0x123456000000789a
188  ret i64 %or
189}
190
191;; Test that bstrins.d is not generated because constant OR operand
192;; doesn't fit into bits cleared by constant AND operand.
193define i64 @no_bstrins_d(i64 %a) nounwind {
194; CHECK-LABEL: no_bstrins_d:
195; CHECK:       # %bb.0:
196; CHECK-NEXT:    lu12i.w $a1, 354185
197; CHECK-NEXT:    lu32i.d $a1, 4660
198; CHECK-NEXT:    or $a0, $a0, $a1
199; CHECK-NEXT:    lu12i.w $a1, 354191
200; CHECK-NEXT:    ori $a1, $a1, 4095
201; CHECK-NEXT:    lu32i.d $a1, -60876
202; CHECK-NEXT:    and $a0, $a0, $a1
203; CHECK-NEXT:    ret
204  %and = and i64 %a, 18446462598732906495 ; 0xffff00000000ffff
205  %or = or i64 %and, 20015998341120       ; 0x0000123456789000
206  ret i64 %or
207}
208