@@ -184,6 +184,196 @@ bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) {
184
184
return false ;
185
185
}
186
186
187
+ // Check that it is a SLOI (Shift Left Ones Immediate). We first check that
188
+ // it is the right node tree:
189
+ //
190
+ // (OR (SHL RS1, VC2), VC1)
191
+ //
192
+ // and then we check that VC1, the mask used to fill with ones, is compatible
193
+ // with VC2, the shamt:
194
+ //
195
+ // VC1 == maskTrailingOnes<uint64_t>(VC2)
196
+
197
+ bool RISCVDAGToDAGISel::SelectSLOI (SDValue N, SDValue &RS1, SDValue &Shamt) {
198
+ MVT XLenVT = Subtarget->getXLenVT ();
199
+ if (N.getOpcode () == ISD::OR) {
200
+ SDValue Or = N;
201
+ if (Or.getOperand (0 ).getOpcode () == ISD::SHL) {
202
+ SDValue Shl = Or.getOperand (0 );
203
+ if (isa<ConstantSDNode>(Shl.getOperand (1 )) &&
204
+ isa<ConstantSDNode>(Or.getOperand (1 ))) {
205
+ if (XLenVT == MVT::i64 ) {
206
+ uint64_t VC1 = Or.getConstantOperandVal (1 );
207
+ uint64_t VC2 = Shl.getConstantOperandVal (1 );
208
+ if (VC1 == maskTrailingOnes<uint64_t >(VC2)) {
209
+ RS1 = Shl.getOperand (0 );
210
+ Shamt = CurDAG->getTargetConstant (VC2, SDLoc (N),
211
+ Shl.getOperand (1 ).getValueType ());
212
+ return true ;
213
+ }
214
+ }
215
+ if (XLenVT == MVT::i32 ) {
216
+ uint32_t VC1 = Or.getConstantOperandVal (1 );
217
+ uint32_t VC2 = Shl.getConstantOperandVal (1 );
218
+ if (VC1 == maskTrailingOnes<uint32_t >(VC2)) {
219
+ RS1 = Shl.getOperand (0 );
220
+ Shamt = CurDAG->getTargetConstant (VC2, SDLoc (N),
221
+ Shl.getOperand (1 ).getValueType ());
222
+ return true ;
223
+ }
224
+ }
225
+ }
226
+ }
227
+ }
228
+ return false ;
229
+ }
230
+
231
+ // Check that it is a SROI (Shift Right Ones Immediate). We first check that
232
+ // it is the right node tree:
233
+ //
234
+ // (OR (SRL RS1, VC2), VC1)
235
+ //
236
+ // and then we check that VC1, the mask used to fill with ones, is compatible
237
+ // with VC2, the shamt:
238
+ //
239
+ // VC1 == maskLeadingOnes<uint64_t>(VC2)
240
+
241
+ bool RISCVDAGToDAGISel::SelectSROI (SDValue N, SDValue &RS1, SDValue &Shamt) {
242
+ MVT XLenVT = Subtarget->getXLenVT ();
243
+ if (N.getOpcode () == ISD::OR) {
244
+ SDValue Or = N;
245
+ if (Or.getOperand (0 ).getOpcode () == ISD::SRL) {
246
+ SDValue Srl = Or.getOperand (0 );
247
+ if (isa<ConstantSDNode>(Srl.getOperand (1 )) &&
248
+ isa<ConstantSDNode>(Or.getOperand (1 ))) {
249
+ if (XLenVT == MVT::i64 ) {
250
+ uint64_t VC1 = Or.getConstantOperandVal (1 );
251
+ uint64_t VC2 = Srl.getConstantOperandVal (1 );
252
+ if (VC1 == maskLeadingOnes<uint64_t >(VC2)) {
253
+ RS1 = Srl.getOperand (0 );
254
+ Shamt = CurDAG->getTargetConstant (VC2, SDLoc (N),
255
+ Srl.getOperand (1 ).getValueType ());
256
+ return true ;
257
+ }
258
+ }
259
+ if (XLenVT == MVT::i32 ) {
260
+ uint32_t VC1 = Or.getConstantOperandVal (1 );
261
+ uint32_t VC2 = Srl.getConstantOperandVal (1 );
262
+ if (VC1 == maskLeadingOnes<uint32_t >(VC2)) {
263
+ RS1 = Srl.getOperand (0 );
264
+ Shamt = CurDAG->getTargetConstant (VC2, SDLoc (N),
265
+ Srl.getOperand (1 ).getValueType ());
266
+ return true ;
267
+ }
268
+ }
269
+ }
270
+ }
271
+ }
272
+ return false ;
273
+ }
274
+
275
+ // Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32
276
+ // on RV64).
277
+ // SLLIUW is the same as SLLI except for the fact that it clears the bits
278
+ // XLEN-1:32 of the input RS1 before shifting.
279
+ // We first check that it is the right node tree:
280
+ //
281
+ // (AND (SHL RS1, VC2), VC1)
282
+ //
283
+ // We check that VC2, the shamt is less than 32, otherwise the pattern is
284
+ // exactly the same as SLLI and we give priority to that.
285
+ // Eventually we check that that VC1, the mask used to clear the upper 32 bits
286
+ // of RS1, is correct:
287
+ //
288
+ // VC1 == (0xFFFFFFFF << VC2)
289
+
290
+ bool RISCVDAGToDAGISel::SelectSLLIUW (SDValue N, SDValue &RS1, SDValue &Shamt) {
291
+ if (N.getOpcode () == ISD::AND && Subtarget->getXLenVT () == MVT::i64 ) {
292
+ SDValue And = N;
293
+ if (And.getOperand (0 ).getOpcode () == ISD::SHL) {
294
+ SDValue Shl = And.getOperand (0 );
295
+ if (isa<ConstantSDNode>(Shl.getOperand (1 )) &&
296
+ isa<ConstantSDNode>(And.getOperand (1 ))) {
297
+ uint64_t VC1 = And.getConstantOperandVal (1 );
298
+ uint64_t VC2 = Shl.getConstantOperandVal (1 );
299
+ if (VC2 < 32 && VC1 == ((uint64_t )0xFFFFFFFF << VC2)) {
300
+ RS1 = Shl.getOperand (0 );
301
+ Shamt = CurDAG->getTargetConstant (VC2, SDLoc (N),
302
+ Shl.getOperand (1 ).getValueType ());
303
+ return true ;
304
+ }
305
+ }
306
+ }
307
+ }
308
+ return false ;
309
+ }
310
+
311
+ // Check that it is a SLOIW (Shift Left Ones Immediate i32 on RV64).
312
+ // We first check that it is the right node tree:
313
+ //
314
+ // (SIGN_EXTEND_INREG (OR (SHL RS1, VC2), VC1))
315
+ //
316
+ // and then we check that VC1, the mask used to fill with ones, is compatible
317
+ // with VC2, the shamt:
318
+ //
319
+ // VC1 == maskTrailingOnes<uint32_t>(VC2)
320
+
321
+ bool RISCVDAGToDAGISel::SelectSLOIW (SDValue N, SDValue &RS1, SDValue &Shamt) {
322
+ if (Subtarget->getXLenVT () == MVT::i64 &&
323
+ N.getOpcode () == ISD::SIGN_EXTEND_INREG &&
324
+ cast<VTSDNode>(N.getOperand (1 ))->getVT () == MVT::i32 ) {
325
+ if (N.getOperand (0 ).getOpcode () == ISD::OR) {
326
+ SDValue Or = N.getOperand (0 );
327
+ if (Or.getOperand (0 ).getOpcode () == ISD::SHL) {
328
+ SDValue Shl = Or.getOperand (0 );
329
+ if (isa<ConstantSDNode>(Shl.getOperand (1 )) &&
330
+ isa<ConstantSDNode>(Or.getOperand (1 ))) {
331
+ uint32_t VC1 = Or.getConstantOperandVal (1 );
332
+ uint32_t VC2 = Shl.getConstantOperandVal (1 );
333
+ if (VC1 == maskTrailingOnes<uint32_t >(VC2)) {
334
+ RS1 = Shl.getOperand (0 );
335
+ Shamt = CurDAG->getTargetConstant (VC2, SDLoc (N),
336
+ Shl.getOperand (1 ).getValueType ());
337
+ return true ;
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
343
+ return false ;
344
+ }
345
+
346
+ // Check that it is a SROIW (Shift Right Ones Immediate i32 on RV64).
347
+ // We first check that it is the right node tree:
348
+ //
349
+ // (OR (SHL RS1, VC2), VC1)
350
+ //
351
+ // and then we check that VC1, the mask used to fill with ones, is compatible
352
+ // with VC2, the shamt:
353
+ //
354
+ // VC1 == maskLeadingOnes<uint32_t>(VC2)
355
+
356
+ bool RISCVDAGToDAGISel::SelectSROIW (SDValue N, SDValue &RS1, SDValue &Shamt) {
357
+ if (N.getOpcode () == ISD::OR && Subtarget->getXLenVT () == MVT::i64 ) {
358
+ SDValue Or = N;
359
+ if (Or.getOperand (0 ).getOpcode () == ISD::SRL) {
360
+ SDValue Srl = Or.getOperand (0 );
361
+ if (isa<ConstantSDNode>(Srl.getOperand (1 )) &&
362
+ isa<ConstantSDNode>(Or.getOperand (1 ))) {
363
+ uint32_t VC1 = Or.getConstantOperandVal (1 );
364
+ uint32_t VC2 = Srl.getConstantOperandVal (1 );
365
+ if (VC1 == maskLeadingOnes<uint32_t >(VC2)) {
366
+ RS1 = Srl.getOperand (0 );
367
+ Shamt = CurDAG->getTargetConstant (VC2, SDLoc (N),
368
+ Srl.getOperand (1 ).getValueType ());
369
+ return true ;
370
+ }
371
+ }
372
+ }
373
+ }
374
+ return false ;
375
+ }
376
+
187
377
// Merge an ADDI into the offset of a load/store instruction where possible.
188
378
// (load (addi base, off1), off2) -> (load base, off1+off2)
189
379
// (store val, (addi base, off1), off2) -> (store val, base, off1+off2)
0 commit comments