@@ -87,6 +87,7 @@ struct RISCVLoadStoreOpt : public MachineFunctionPass {
8787 bool isConsecutiveRegPair (Register First, Register Second);
8888 void splitLdSdIntoTwo (MachineBasicBlock &MBB,
8989 MachineBasicBlock::iterator &MBBI, bool IsLoad);
90+ int64_t getLoadStoreOffset (const MachineInstr &MI);
9091
9192private:
9293 AliasAnalysis *AA;
@@ -427,10 +428,27 @@ RISCVLoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
427428// Post reg-alloc zilsd pass implementation
428429// ===----------------------------------------------------------------------===//
429430
431+ // Helper function to extract offset from load/store operands
432+ int64_t RISCVLoadStoreOpt::getLoadStoreOffset (const MachineInstr &MI) {
433+ const MachineOperand &OffsetOp = MI.getOperand (2 );
434+
435+ // Handle immediate offset
436+ if (OffsetOp.isImm ())
437+ return OffsetOp.getImm ();
438+
439+ // Handle symbolic operands with MO_LO flag (from MergeBaseOffset)
440+ if (OffsetOp.getTargetFlags () & RISCVII::MO_LO)
441+ if (OffsetOp.isGlobal () || OffsetOp.isCPI () || OffsetOp.isBlockAddress () ||
442+ OffsetOp.isSymbol ())
443+ return OffsetOp.getOffset ();
444+
445+ return 0 ;
446+ }
447+
430448bool RISCVLoadStoreOpt::isConsecutiveRegPair (Register First, Register Second) {
431- // Special case: both registers are zero register - this is valid for storing
449+ // Special case: First register can not be zero
432450 // zeros
433- if (First == RISCV::X0 && Second == RISCV::X0 )
451+ if (First == RISCV::X0)
434452 return true ;
435453
436454 // Check if registers form a valid even/odd pair for Zilsd
@@ -450,21 +468,53 @@ void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &MBB,
450468 Register FirstReg = MI->getOperand (0 ).getReg ();
451469 Register SecondReg = MI->getOperand (1 ).getReg ();
452470 Register BaseReg = MI->getOperand (2 ).getReg ();
453- int Offset = MI->getOperand (3 ).getImm ();
471+
472+ // Handle both immediate and symbolic operands for offset
473+ const MachineOperand &OffsetOp = MI->getOperand (3 );
474+ int BaseOffset;
475+ if (OffsetOp.isImm ())
476+ BaseOffset = OffsetOp.getImm ();
477+ else
478+ // For symbolic operands, extract the embedded offset
479+ BaseOffset = OffsetOp.getOffset ();
454480
455481 unsigned Opc = IsLoad ? RISCV::LW : RISCV::SW;
456482
457483 // Create two separate instructions
458484 if (IsLoad) {
459485 auto MIB1 = BuildMI (MBB, MBBI, DL, TII->get (Opc))
460486 .addReg (FirstReg, RegState::Define)
461- .addReg (BaseReg)
462- .addImm (Offset);
487+ .addReg (BaseReg);
463488
464489 auto MIB2 = BuildMI (MBB, MBBI, DL, TII->get (Opc))
465490 .addReg (SecondReg, RegState::Define)
466- .addReg (BaseReg)
467- .addImm (Offset + 4 );
491+ .addReg (BaseReg);
492+
493+ // Add offset operands - preserve symbolic references
494+ if (OffsetOp.isImm ()) {
495+ MIB1.addImm (BaseOffset);
496+ MIB2.addImm (BaseOffset + 4 );
497+ } else if (OffsetOp.isGlobal ()) {
498+ MIB1.addGlobalAddress (OffsetOp.getGlobal (), BaseOffset,
499+ OffsetOp.getTargetFlags ());
500+ MIB2.addGlobalAddress (OffsetOp.getGlobal (), BaseOffset + 4 ,
501+ OffsetOp.getTargetFlags ());
502+ } else if (OffsetOp.isCPI ()) {
503+ MIB1.addConstantPoolIndex (OffsetOp.getIndex (), BaseOffset,
504+ OffsetOp.getTargetFlags ());
505+ MIB2.addConstantPoolIndex (OffsetOp.getIndex (), BaseOffset + 4 ,
506+ OffsetOp.getTargetFlags ());
507+ } else if (OffsetOp.isSymbol ()) {
508+ MIB1.addExternalSymbol (OffsetOp.getSymbolName (),
509+ OffsetOp.getTargetFlags ());
510+ MIB2.addExternalSymbol (OffsetOp.getSymbolName (),
511+ OffsetOp.getTargetFlags ());
512+ } else if (OffsetOp.isBlockAddress ()) {
513+ MIB1.addBlockAddress (OffsetOp.getBlockAddress (), BaseOffset,
514+ OffsetOp.getTargetFlags ());
515+ MIB2.addBlockAddress (OffsetOp.getBlockAddress (), BaseOffset + 4 ,
516+ OffsetOp.getTargetFlags ());
517+ }
468518
469519 // Copy memory operands if the original instruction had them
470520 // FIXME: This is overly conservative; the new instruction accesses 4 bytes,
@@ -477,15 +527,37 @@ void RISCVLoadStoreOpt::splitLdSdIntoTwo(MachineBasicBlock &MBB,
477527 ++NumLD2LW;
478528 LLVM_DEBUG (dbgs () << " Split LD back to two LW instructions\n " );
479529 } else {
480- auto MIB1 = BuildMI (MBB, MBBI, DL, TII->get (Opc))
481- .addReg (FirstReg)
482- .addReg (BaseReg)
483- .addImm (Offset);
484-
485- auto MIB2 = BuildMI (MBB, MBBI, DL, TII->get (Opc))
486- .addReg (SecondReg)
487- .addReg (BaseReg)
488- .addImm (Offset + 4 );
530+ auto MIB1 =
531+ BuildMI (MBB, MBBI, DL, TII->get (Opc)).addReg (FirstReg).addReg (BaseReg);
532+
533+ auto MIB2 =
534+ BuildMI (MBB, MBBI, DL, TII->get (Opc)).addReg (SecondReg).addReg (BaseReg);
535+
536+ // Add offset operands - preserve symbolic references
537+ if (OffsetOp.isImm ()) {
538+ MIB1.addImm (BaseOffset);
539+ MIB2.addImm (BaseOffset + 4 );
540+ } else if (OffsetOp.isGlobal ()) {
541+ MIB1.addGlobalAddress (OffsetOp.getGlobal (), BaseOffset,
542+ OffsetOp.getTargetFlags ());
543+ MIB2.addGlobalAddress (OffsetOp.getGlobal (), BaseOffset + 4 ,
544+ OffsetOp.getTargetFlags ());
545+ } else if (OffsetOp.isCPI ()) {
546+ MIB1.addConstantPoolIndex (OffsetOp.getIndex (), BaseOffset,
547+ OffsetOp.getTargetFlags ());
548+ MIB2.addConstantPoolIndex (OffsetOp.getIndex (), BaseOffset + 4 ,
549+ OffsetOp.getTargetFlags ());
550+ } else if (OffsetOp.isSymbol ()) {
551+ MIB1.addExternalSymbol (OffsetOp.getSymbolName (),
552+ OffsetOp.getTargetFlags ());
553+ MIB2.addExternalSymbol (OffsetOp.getSymbolName (),
554+ OffsetOp.getTargetFlags ());
555+ } else if (OffsetOp.isBlockAddress ()) {
556+ MIB1.addBlockAddress (OffsetOp.getBlockAddress (), BaseOffset,
557+ OffsetOp.getTargetFlags ());
558+ MIB2.addBlockAddress (OffsetOp.getBlockAddress (), BaseOffset + 4 ,
559+ OffsetOp.getTargetFlags ());
560+ }
489561
490562 // Copy memory operands if the original instruction had them
491563 // FIXME: This is overly conservative; the new instruction accesses 4 bytes,
@@ -526,8 +598,15 @@ bool RISCVLoadStoreOpt::fixInvalidRegPairOp(MachineBasicBlock &MBB,
526598
527599 // Registers are valid, convert to real LD/SD instruction
528600 Register BaseReg = MI->getOperand (2 ).getReg ();
529- int Offset = MI->getOperand (3 ).getImm ();
530601 DebugLoc DL = MI->getDebugLoc ();
602+ // Handle both immediate and symbolic operands for offset
603+ const MachineOperand &OffsetOp = MI->getOperand (3 );
604+ int BaseOffset;
605+ if (OffsetOp.isImm ())
606+ BaseOffset = OffsetOp.getImm ();
607+ else
608+ // For symbolic operands, extract the embedded offset
609+ BaseOffset = OffsetOp.getOffset ();
531610
532611 unsigned RealOpc = IsLoad ? RISCV::LD_RV32 : RISCV::SD_RV32;
533612
@@ -545,7 +624,22 @@ bool RISCVLoadStoreOpt::fixInvalidRegPairOp(MachineBasicBlock &MBB,
545624 MIB.addReg (RegPair);
546625 }
547626
548- MIB.addReg (BaseReg).addImm (Offset);
627+ MIB.addReg (BaseReg);
628+
629+ // Add offset operand - preserve symbolic references
630+ if (OffsetOp.isImm ())
631+ MIB.addImm (BaseOffset);
632+ else if (OffsetOp.isGlobal ())
633+ MIB.addGlobalAddress (OffsetOp.getGlobal (), BaseOffset,
634+ OffsetOp.getTargetFlags ());
635+ else if (OffsetOp.isCPI ())
636+ MIB.addConstantPoolIndex (OffsetOp.getIndex (), BaseOffset,
637+ OffsetOp.getTargetFlags ());
638+ else if (OffsetOp.isSymbol ())
639+ MIB.addExternalSymbol (OffsetOp.getSymbolName (), OffsetOp.getTargetFlags ());
640+ else if (OffsetOp.isBlockAddress ())
641+ MIB.addBlockAddress (OffsetOp.getBlockAddress (), BaseOffset,
642+ OffsetOp.getTargetFlags ());
549643
550644 // Copy memory operands if the original instruction had them
551645 if (MI->memoperands_begin () != MI->memoperands_end ())
0 commit comments