@@ -362,6 +362,8 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi,
362
362
// Tail: lw vreg3, 8(vreg2)
363
363
364
364
std::optional<int64_t > CommonOffset;
365
+ DenseMap<const MachineInstr *, SmallVector<unsigned >>
366
+ InlineAsmMemoryOpIndexesMap;
365
367
for (const MachineInstr &UseMI : MRI->use_instructions (DestReg)) {
366
368
switch (UseMI.getOpcode ()) {
367
369
default :
@@ -396,6 +398,49 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi,
396
398
if (CommonOffset && Offset != CommonOffset)
397
399
return false ;
398
400
CommonOffset = Offset;
401
+ break ;
402
+ }
403
+ case RISCV::INLINEASM:
404
+ case RISCV::INLINEASM_BR: {
405
+ SmallVector<unsigned > InlineAsmMemoryOpIndexes;
406
+ unsigned NumOps = 0 ;
407
+ for (unsigned I = InlineAsm::MIOp_FirstOperand;
408
+ I < UseMI.getNumOperands (); I += 1 + NumOps) {
409
+ const MachineOperand &FlagsMO = UseMI.getOperand (I);
410
+ // Should be an imm.
411
+ if (!FlagsMO.isImm ())
412
+ continue ;
413
+
414
+ const InlineAsm::Flag Flags (FlagsMO.getImm ());
415
+ NumOps = Flags.getNumOperandRegisters ();
416
+
417
+ // Memory constraints have two operands.
418
+ if (NumOps != 2 || !Flags.isMemKind ())
419
+ continue ;
420
+
421
+ // We can't do this for constraint A because AMO instructions don't have
422
+ // an immediate offset field.
423
+ if (Flags.getMemoryConstraintID () == InlineAsm::ConstraintCode::A)
424
+ return false ;
425
+
426
+ const MachineOperand &AddrMO = UseMI.getOperand (I + 1 );
427
+ if (!AddrMO.isReg () || AddrMO.getReg () != DestReg)
428
+ continue ;
429
+
430
+ const MachineOperand &OffsetMO = UseMI.getOperand (I + 2 );
431
+ if (!OffsetMO.isImm ())
432
+ continue ;
433
+
434
+ // All inline asm memory operands must use the same offset.
435
+ int64_t Offset = OffsetMO.getImm ();
436
+ if (CommonOffset && Offset != CommonOffset)
437
+ return false ;
438
+ CommonOffset = Offset;
439
+ InlineAsmMemoryOpIndexes.push_back (I + 1 );
440
+ }
441
+ InlineAsmMemoryOpIndexesMap.insert (
442
+ std::make_pair (&UseMI, InlineAsmMemoryOpIndexes));
443
+ break ;
399
444
}
400
445
}
401
446
}
@@ -420,13 +465,36 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi,
420
465
// Update the immediate in the load/store instructions to add the offset.
421
466
for (MachineInstr &UseMI :
422
467
llvm::make_early_inc_range (MRI->use_instructions (DestReg))) {
423
- UseMI.removeOperand (2 );
424
- UseMI.addOperand (ImmOp);
425
- // Update the base reg in the Tail instruction to feed from LUI.
426
- // Output of Hi is only used in Lo, no need to use MRI->replaceRegWith().
427
- UseMI.getOperand (1 ).setReg (Hi.getOperand (0 ).getReg ());
468
+ if (UseMI.getOpcode () == RISCV::INLINEASM ||
469
+ UseMI.getOpcode () == RISCV::INLINEASM_BR) {
470
+ auto &InlineAsmMemoryOpIndexes = InlineAsmMemoryOpIndexesMap[&UseMI];
471
+ for (unsigned I : InlineAsmMemoryOpIndexes) {
472
+ MachineOperand &MO = UseMI.getOperand (I + 1 );
473
+ switch (ImmOp.getType ()) {
474
+ case MachineOperand::MO_GlobalAddress:
475
+ MO.ChangeToGA (ImmOp.getGlobal (), ImmOp.getOffset (),
476
+ ImmOp.getTargetFlags ());
477
+ break ;
478
+ case MachineOperand::MO_MCSymbol:
479
+ MO.ChangeToMCSymbol (ImmOp.getMCSymbol (), ImmOp.getTargetFlags ());
480
+ MO.setOffset (ImmOp.getOffset ());
481
+ break ;
482
+ case MachineOperand::MO_BlockAddress:
483
+ MO.ChangeToBA (ImmOp.getBlockAddress (), ImmOp.getOffset (),
484
+ ImmOp.getTargetFlags ());
485
+ break ;
486
+ default :
487
+ report_fatal_error (" unsupported machine operand type" );
488
+ break ;
489
+ }
490
+ }
491
+ } else {
492
+ UseMI.removeOperand (2 );
493
+ UseMI.addOperand (ImmOp);
494
+ }
428
495
}
429
496
497
+ MRI->replaceRegWith (Lo.getOperand (0 ).getReg (), Hi.getOperand (0 ).getReg ());
430
498
Lo.eraseFromParent ();
431
499
return true ;
432
500
}
0 commit comments