@@ -91,3 +91,222 @@ def TuneLDADDFusion
9191 CheckIsImmOperand<2>,
9292 CheckImmOperand<2, 0>
9393 ]>>;
94+
95+ // Get lower 16 bits:
96+ // slliw r1, r0, 16
97+ // srliw r1, r1, 16
98+ def GetLower16BitsFusion
99+ : SimpleFusion<"get-lower-16bits-fusion", "HasGetLower16BitsFusion",
100+ "Enable SLLIW+SRLIW to be fused to get lower 16 bits",
101+ CheckAll<[
102+ CheckOpcode<[SLLIW]>,
103+ CheckImmOperand<2, 16>
104+ ]>,
105+ CheckAll<[
106+ CheckOpcode<[SRLIW]>,
107+ CheckImmOperand<2, 16>
108+ ]>>;
109+
110+ // Sign-extend a 16-bit number:
111+ // slliw r1, r0, 16
112+ // sraiw r1, r1, 16
113+ def SExtHFusion
114+ : SimpleFusion<"sign-extend-16bits-fusion","HasSExtHFusion",
115+ "Enable SLLIW+SRAIW to be fused to sign-extend a 16-bit number",
116+ CheckAll<[
117+ CheckOpcode<[SLLIW]>,
118+ CheckImmOperand<2, 16>
119+ ]>,
120+ CheckAll<[
121+ CheckOpcode<[SRAIW]>,
122+ CheckImmOperand<2, 16>
123+ ]>>;
124+
125+ // These should be covered by Zba extension.
126+ // * shift left by one and add:
127+ // slli r1, r0, 1
128+ // add r1, r1, r2
129+ // * shift left by two and add:
130+ // slli r1, r0, 2
131+ // add r1, r1, r2
132+ // * shift left by three and add:
133+ // slli r1, r0, 3
134+ // add r1, r1, r2
135+ let IsCommutable = 1 in
136+ def ShiftNAddFusion
137+ : SimpleFusion<"shift-n-add-fusion", "HasShiftNAddFusion",
138+ "Enable SLLI+ADD to be fused to shift left by 1/2/3 and add",
139+ CheckAll<[
140+ CheckOpcode<[SLLI]>,
141+ CheckAny<[CheckImmOperand<2, 1>,
142+ CheckImmOperand<2, 2>,
143+ CheckImmOperand<2, 3>]>
144+ ]>,
145+ CheckOpcode<[ADD]>>;
146+
147+ // * Shift zero-extended word left by 1:
148+ // slli r1, r0, 32
149+ // srli r1, r0, 31
150+ // * Shift zero-extended word left by 2:
151+ // slli r1, r0, 32
152+ // srli r1, r0, 30
153+ // * Shift zero-extended word left by 3:
154+ // slli r1, r0, 32
155+ // srli r1, r0, 29
156+ def ShiftZExtByNFusion
157+ : SimpleFusion<"shift-zext-by-n-fusion", "HasShiftZExtByNFusion",
158+ "Enable SLLI+SRLI to be fused to shift zero-extended word left by 1/2/3",
159+ CheckAll<[
160+ CheckOpcode<[SLLI]>,
161+ CheckImmOperand<2, 32>
162+ ]>,
163+ CheckAll<[
164+ CheckOpcode<[SRLI]>,
165+ CheckAny<[CheckImmOperand<2, 29>,
166+ CheckImmOperand<2, 30>,
167+ CheckImmOperand<2, 31>]>
168+ ]>>;
169+
170+ // Get the second byte:
171+ // srli r1, r0, 8
172+ // andi r1, r1, 255
173+ def GetSecondByteFusion
174+ : SimpleFusion<"get-second-byte-fusion", "HasGetSecondByteFusion",
175+ "Enable SRLI+ANDI to be fused to get the second byte",
176+ CheckAll<[
177+ CheckOpcode<[SRLI]>,
178+ CheckImmOperand<2, 8>
179+ ]>,
180+ CheckAll<[
181+ CheckOpcode<[ANDI]>,
182+ CheckImmOperand<2, 255>
183+ ]>>;
184+
185+ // Shift left by four and add:
186+ // slli r1, r0, 4
187+ // add r1, r1, r2
188+ let IsCommutable = 1 in
189+ def ShiftLeft4AddFusion
190+ : SimpleFusion<"shift-left-four-add-fusion", "HasShiftLeft4AddFusion",
191+ "Enable SLLI+ADD to be fused to shift left by four and add",
192+ CheckAll<[
193+ CheckOpcode<[SLLI]>,
194+ CheckImmOperand<2, 4>
195+ ]>,
196+ CheckOpcode<[ADD]>>;
197+
198+ // * Shift right by 29 and add:
199+ // srli r1, r0, 29
200+ // add r1, r1, r2
201+ // * Shift right by 30 and add:
202+ // srli r1, r0, 30
203+ // add r1, r1, r2
204+ // * Shift right by 31 and add:
205+ // srli r1, r0, 31
206+ // add r1, r1, r2
207+ // * Shift right by 32 and add:
208+ // srli r1, r0, 32
209+ // add r1, r1, r2
210+ let IsCommutable = 1 in
211+ def ShiftRightNAddFusion
212+ : SimpleFusion<"shift-right-n-add-fusion", "HasShiftRightNAddFusion",
213+ "Enable SRLI+add to be fused to shift right by 29/30/31/32 and add",
214+ CheckAll<[
215+ CheckOpcode<[SRLI]>,
216+ CheckAny<[CheckImmOperand<2, 29>,
217+ CheckImmOperand<2, 30>,
218+ CheckImmOperand<2, 31>,
219+ CheckImmOperand<2, 32>]>
220+ ]>,
221+ CheckOpcode<[ADD]>>;
222+
223+ // Add one if odd, otherwise unchanged:
224+ // andi r1, r0, 1
225+ // add r1, r1, r2
226+ // Add one if odd (in word format), otherwise unchanged:
227+ // andi r1, r0, 1
228+ // addw r1, r1, r2
229+ let IsCommutable = 1 in
230+ def AddOneIfOddFusion
231+ : SimpleFusion<"add-one-if-odd-fusion", "HasAddOneIfOddFusion",
232+ "Enable ANDI+ADDW to be fused to add one if odd",
233+ CheckAll<[
234+ CheckOpcode<[ANDI]>,
235+ CheckImmOperand<2, 1>
236+ ]>,
237+ CheckOpcode<[ADD, ADDW]>>;
238+
239+ // * Add word and extract its lower 1 bit:
240+ // andw r1, r1, r0
241+ // andi r1, r1, 1
242+ // * Add word and extract its lower 8 bits:
243+ // andw r1, r1, r0
244+ // andi r1, r1, 255
245+ def AddAndExtractNBitsFusion
246+ : SimpleFusion<"add-and-extract-n-bits-fusion", "HasAddAndExtractNBitsFusion",
247+ "Enable ADDW+ANDI to be fused to get lower 16 bits",
248+ CheckOpcode<[ADDW]>,
249+ CheckAll<[
250+ CheckOpcode<[ANDI]>,
251+ CheckAny<[CheckImmOperand<2, 1>,
252+ CheckImmOperand<2, 255>]>
253+ ]>>;
254+
255+ // * Add word and zext.h:
256+ // andw r1, r1, r0
257+ // zext.h r1, r1
258+ // * Add word and sext.h:
259+ // andw r1, r1, r0
260+ // sext.h r1, r1
261+ def AddwAndExtFusion
262+ : SimpleFusion<"addw-and-ext-fusion", "HasAddwAndExtFusion",
263+ "Enable ADDW+ZEXT_H/SEXT_H to be fused",
264+ CheckOpcode<[ADDW]>,
265+ CheckOpcode<[ZEXT_H_RV32, ZEXT_H_RV64, SEXT_H]>>;
266+
267+ // Logic operation and extract its LSB:
268+ // <logic op> r1, r1, r0
269+ // andi r1, r1, 1
270+ def LogicOpAndExtractLSBFusion
271+ : SimpleFusion<"logic-op-and-extract-lsb-fusion", "HasLogicOpAndExtractLSBFusion",
272+ "Enable AND/OR/XOR/ANDI/ORI/XORI/ORC_B+ANDI to be fused to logic operation and extract its LSB",
273+ CheckOpcode<[AND, OR, XOR, ANDI, ORI, XORI, ORC_B]>,
274+ CheckAll<[
275+ CheckOpcode<[ANDI]>,
276+ CheckImmOperand<2, 1>
277+ ]>>;
278+
279+ // Logic operation and extract its lower 16 bits:
280+ // <logic op> r1, r1, r0
281+ // zext.h r1, r1
282+ def LogicOpAndExtractLow16BitsFusion
283+ : SimpleFusion<"logic-op-and-extract-low-16bits-fusion", "HasLogicOpAndExtractLow16BitsFusion",
284+ "Enable AND/OR/XOR/ANDI/ORI/XORI/ORC_B+ZEXT_H to be fused to logic operation and extract its lower 16 bits",
285+ CheckOpcode<[AND, OR, XOR, ANDI, ORI, XORI, ORC_B]>,
286+ CheckOpcode<[ZEXT_H_RV32, ZEXT_H_RV64]>>;
287+
288+ // OR(Cat(src1(63, 8), 0.U(8.W)), src2):
289+ // andi r1, r0, -256
290+ // or r1, r1, r2
291+ let IsCommutable = 1 in
292+ def OrCatFusion
293+ : SimpleFusion<"or-cat-fusion", "HasOrCatFusion",
294+ "Enable SLLIW+SRLIW to be fused to get lower 16 bits",
295+ CheckAll<[
296+ CheckOpcode<[ANDI]>,
297+ CheckImmOperand<2, -256>
298+ ]>,
299+ CheckOpcode<[OR]>>;
300+
301+ // Multiply 7-bit data with 32-bit data:
302+ // andi r1, r0, 127
303+ // mulw r1, r1, r2
304+ let IsCommutable = 1 in
305+ def Mul7BitsWith32BitsFusion
306+ : SimpleFusion<"mul-7bits-with-32bit-fusion", "HasMul7BitsWith32BitsFusion",
307+ "Enable ANDI+MULW to be fused to multiply 7-bit data with 32-bit data",
308+ CheckAll<[
309+ CheckOpcode<[ANDI]>,
310+ CheckImmOperand<2, 127>
311+ ]>,
312+ CheckOpcode<[MULW]>>;
0 commit comments