MachineMemOperand and dependence information

I have two questions regarding MachineMemOperands and dependence information.

Q1) I noticed that MachineMemOperands are lost when two LDRs are combined and a LDRD is generated in ARMPreAllocLoadStoreOpt:::RescheduleOps.

(before optimization)
%reg1033 = LDR %reg1030, %reg0, 4100, pred:14, pred:%reg0; mem:LD4[%uglygep10]
%reg1054 = LDR %reg1030, %reg0, 4104, pred:14, pred:%reg0; mem:LD4[%uglygep2021]

(after optimization)
%reg1054, %reg1033 = LDRD %reg1030, %reg0, 264, pred:14, pred:%reg0

Are there any reasons they need to be removed?
Would it break something if both MachineMemOperands were added to the newly generated instruction?

(after optimization)
%reg1054, %reg1033 = LDRD %reg1030, %reg0, 264, pred:14, pred:%reg0; mem:LD4[%uglygep10], mem:LD4[%uglygep2021]

Q2) If a pass generates new instructions and it is not possible to add MachineMemOperands in a way that correctly reflects dependence information, should the MachineMemOperands be removed altogether? The pass I am writing does something similar to loop unrolling and replicates and reorders existing instructions.

For example, a single load instruction could be replicated three times.
(before transformation)
%reg1033 = LDR %reg1030, %reg0, 4100, pred:14, pred:%reg0; mem:LD4[%uglygep10]

(after transformation)
%reg1043 = LDR %reg1040, %reg0, 4100, pred:14, pred:%reg0; mem:LD4[%uglygep10]

%reg1053 = LDR %reg1050, %reg0, 4100, pred:14, pred:%reg0; mem:LD4[%uglygep10]

%reg1063 = LDR %reg1060, %reg0, 4100, pred:14, pred:%reg0; mem:LD4[%uglygep10]

In this example, should mem:LD4[%uglygep10] be removed from the three instructions so that passes run later will not use dependence information that is no longer correct?

Thank you.

If I had to guess, I would think it's because of how LDR is defined:

def addrmodepc : Operand<i32>,
                 ComplexPattern<i32, 2, "SelectAddrModePC", > {
  let PrintMethod = "printAddrModePCOperand";
  let MIOperandInfo = (ops GPR, i32imm);
def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr,
               "ldr", "\t$dst, $addr",
               [(set GPR:$dst, (load addrmode2:$addr))]>;

It's using addrmodepc, which is a ComplexPattern. The TableGen code cannot handle resetting the memoperands if it's dealing with a ComplexPattern. There's a similar bug in the X86 target.


Thank you for replying to my email.

I am not sure if I understand your point, but are you suggesting this is done during instruction selection? It seems that this transformation takes place inside ARMPreAllocLoadStoreOpt:::RescheduleOps (after line 1501).

01504           Ops.[pop_back](;

01505           Ops.[pop_back](;
01507           // Form the pair instruction.

01508           if (isLd) {
01509             [MachineInstrBuilder]( MIB = [BuildMI](*MBB, InsertPos,

01510                                               dl, TII->get(NewOpc))
01511               .addReg(EvenReg, [RegState::Define](

01512               .[addReg](, [RegState::Define](

01513               .[addReg](;
01514             if (!isT2)

01515               MIB.[addReg](;
01516             MIB.[addImm]([addImm]([addReg](;

01517             ++NumLDRDFormed;

I just wanted to know whether or not the MachineMemOperands were intentionally left out and if it is okay to add the MachineMemOperands to the newly created instruction (would it break anything?).

Thank you.

Sorry, this is the part in ARMLoadStoreOptimizer.cpp that creates a LDRD instruction.


// Form the pair instruction.
if (isLd) {
MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos,
dl, TII->get(NewOpc))
.addReg(EvenReg, RegState::Define)
.addReg(OddReg, RegState::Define)
if (!isT2)

Ah! Okay. So it’s not the generic code. Yes, it’s probably a bug that the memoperands aren’t propagated to the new instruction. Please file a bug report with a small testcase.