@@ -315,7 +315,25 @@ std::unique_ptr<GenericCombiner> OffsetCombiner::clone() const {
315315
316316std::optional<std::pair<std::vector<SUnit *>, std::vector<SUnit *>>>
317317OffsetCombiner::getInstructionsToMove (const AIE::DataDependenceHelper &DAG) {
318- return {{/* MoveUp*/ {}, /* MoveDown*/ {}}};
318+ auto *PtrAdd = getPtrInc ();
319+ if (!getImm (*PtrAdd, *MRI)) {
320+ // / Offset is not an immediate and the OffsetCombiner is not eligible for
321+ // / reordering.
322+ // Since the Offset already dominates the MemoryInstruction (where the
323+ // insertion happens), no checks have to be performed.
324+ return {{/* MoveUp=*/ {}, /* MoveDown=*/ {}}};
325+ }
326+
327+ auto *SUnitPtrAdd = DAG.getSUnit (PtrAdd);
328+ if (!SUnitPtrAdd) {
329+ // / PtrAdd is an Immediate but it is outside of the MBB, so it already
330+ // / dominates the MemoryInstruction. No checks have to be performed.
331+ return {{/* MoveUp=*/ {}, /* MoveDown=*/ {}}};
332+ }
333+
334+ // / Immediate Offset can be a reordering Candidate. Therefore, track Immediate
335+ // / Offset, so it can be moved in case of a reordering.
336+ return {{/* MoveUp=*/ {SUnitPtrAdd}, /* MoveDown=*/ {}}};
319337}
320338
321339void OffsetCombiner::adjustGain (const MachineDominatorTree &MDT) {
@@ -335,7 +353,7 @@ void OffsetCombiner::adjustGain(const MachineDominatorTree &MDT) {
335353 Gain.setPtrMod (0 );
336354 }
337355
338- std::optional<APInt> ImmOffset = getImm (*PtrAdd, *MRI);
356+ ImmOffset = getImm (*PtrAdd, *MRI);
339357 if (!ImmOffset)
340358 return ;
341359
@@ -363,6 +381,58 @@ std::optional<unsigned> OffsetCombiner::getOpCode(MachineInstr *PtrInc,
363381 return TII->getOffsetMemOpcode (MemI->getOpcode ());
364382}
365383
384+ bool OffsetCombiner::canReorder () const { return ImmOffset.has_value (); }
385+
386+ bool OffsetCombiner::isReorderCandidate (
387+ const GenericCombiner *PostIncCombiner) const {
388+ auto GetInputPtr = [&](const MachineInstr *PtrMod) {
389+ auto InputPtrIdx = PtrModSupport.getInputPtrIdx (*PtrMod);
390+ assert (InputPtrIdx);
391+ return PtrMod->getOperand (*InputPtrIdx);
392+ };
393+
394+ const PointerModifierCombiner *PtrModCombiner =
395+ static_cast <const PointerModifierCombiner *>(PostIncCombiner);
396+ if (!PtrModCombiner->isPostInc ())
397+ return false ;
398+
399+ // only allow loads to be reordered
400+ if (getMemI ()->mayStore () || PtrModCombiner->getMemI ()->mayStore ())
401+ return false ;
402+
403+ // Same MBB check
404+ auto *PtrAdd = getPtrInc ();
405+ auto *PostIncPtrMod = PtrModCombiner->getPtrInc ();
406+ if (PtrAdd->getParent () != PostIncPtrMod->getParent ())
407+ return false ;
408+
409+ // Same Input Ptr Check
410+ auto InputPtr = GetInputPtr (PtrAdd);
411+ auto PostIncInputPtr = GetInputPtr (PostIncPtrMod);
412+ if (!InputPtr.isIdenticalTo (PostIncInputPtr))
413+ return false ;
414+
415+ // Check if Store Instruction of Offset dominates PostInc
416+ auto *MemI = getMemI ();
417+ if (MemI->mayStore ()) {
418+ auto Source = MemI->getOperand (0 );
419+ assert (Source.isReg ());
420+ auto *DefSource = MRI->getUniqueVRegDef (Source.getReg ());
421+ if (!DefSource)
422+ return false ;
423+ auto *DefSUnit = DAG->getSUnit (DefSource);
424+ if (DefSUnit &&
425+ DefSUnit->NodeNum > PostIncCombiner->InsertionPointNodeNum ) {
426+ // Source of Offset-Store would be after the new InsertionPoint and thus
427+ // generate invalid mir
428+ return false ;
429+ }
430+ }
431+
432+ // OffsetCombiner occurs after PostIncCombiner
433+ return InsertionPointNodeNum > PostIncCombiner->InsertionPointNodeNum ;
434+ }
435+
366436// -------------------------- PostIncCombiner --------------------------------//
367437
368438bool PostIncCombiner::isCombineCandidate (MachineInstr &MemI,
0 commit comments