@@ -110,6 +110,9 @@ class CopyTracker {
110110 struct CopyInfo {
111111 MachineInstr *MI = nullptr ;
112112 MachineInstr *LastSeenUseInCopy = nullptr ;
113+ // EraVM local begin
114+ SmallPtrSet<MachineInstr *, 4 > SrcUsers;
115+ // EraVM local end
113116 SmallVector<MCRegister, 4 > DefRegs;
114117 bool Avail = false ;
115118 };
@@ -224,6 +227,45 @@ class CopyTracker {
224227 }
225228 }
226229
230+ // EraVM local begin
231+ // / Track copy's src users, and return false if that can't be done.
232+ // / We can only track if we have a COPY instruction which source is
233+ // / the same as the Reg.
234+ bool trackSrcUsers (MCRegister Reg, MachineInstr &MI,
235+ const TargetRegisterInfo &TRI, const TargetInstrInfo &TII,
236+ bool UseCopyInstr) {
237+ MCRegUnit RU = *TRI.regunits (Reg).begin ();
238+ MachineInstr *AvailCopy = findCopyDefViaUnit (RU, TRI);
239+ if (!AvailCopy)
240+ return false ;
241+
242+ std::optional<DestSourcePair> CopyOperands =
243+ isCopyInstr (*AvailCopy, TII, UseCopyInstr);
244+ Register Src = CopyOperands->Source ->getReg ();
245+
246+ // Bail out, if the source of the copy is not the same as the Reg.
247+ if (Src != Reg)
248+ return false ;
249+
250+ auto I = Copies.find (RU);
251+ if (I == Copies.end ())
252+ return false ;
253+
254+ I->second .SrcUsers .insert (&MI);
255+ return true ;
256+ }
257+
258+ // / Return the users for a given register.
259+ SmallPtrSet<MachineInstr *, 4 > getSrcUsers (MCRegister Reg,
260+ const TargetRegisterInfo &TRI) {
261+ MCRegUnit RU = *TRI.regunits (Reg).begin ();
262+ auto I = Copies.find (RU);
263+ if (I == Copies.end ())
264+ return {};
265+ return I->second .SrcUsers ;
266+ }
267+ // EraVM local end
268+
227269 // / Add this copy's registers into the tracker's copy maps.
228270 void trackCopy (MachineInstr *MI, const TargetRegisterInfo &TRI,
229271 const TargetInstrInfo &TII, bool UseCopyInstr) {
@@ -236,7 +278,9 @@ class CopyTracker {
236278
237279 // Remember Def is defined by the copy.
238280 for (MCRegUnit Unit : TRI.regunits (Def))
239- Copies[Unit] = {MI, nullptr , {}, true };
281+ // EraVM local begin
282+ Copies[Unit] = {MI, nullptr , {}, {}, true };
283+ // EraVM local end
240284
241285 // Remember source that's copied to Def. Once it's clobbered, then
242286 // it's no longer available for copy propagation.
@@ -427,6 +471,10 @@ class MachineCopyPropagation : public MachineFunctionPass {
427471 bool hasImplicitOverlap (const MachineInstr &MI, const MachineOperand &Use);
428472 bool hasOverlappingMultipleDef (const MachineInstr &MI,
429473 const MachineOperand &MODef, Register Def);
474+ // EraVM local begin
475+ bool canUpdateSrcUsers (const MachineInstr &Copy,
476+ const MachineOperand &CopySrc);
477+ // EraVM local end
430478
431479 // / Candidates for deletion.
432480 SmallSetVector<MachineInstr *, 8 > MaybeDeadCopies;
@@ -667,6 +715,28 @@ bool MachineCopyPropagation::hasOverlappingMultipleDef(
667715 return false ;
668716}
669717
718+ // EraVM local begin
719+ // / Return true if it is safe to update the users of the source register of the
720+ // / copy.
721+ bool MachineCopyPropagation::canUpdateSrcUsers (const MachineInstr &Copy,
722+ const MachineOperand &CopySrc) {
723+ for (auto *SrcUser : Tracker.getSrcUsers (CopySrc.getReg (), *TRI)) {
724+ if (hasImplicitOverlap (*SrcUser, CopySrc))
725+ return false ;
726+
727+ for (MachineOperand &MO : SrcUser->uses ()) {
728+ if (!MO.isReg () || !MO.isUse () || MO.getReg () != CopySrc.getReg ())
729+ continue ;
730+ if (MO.isTied () || !MO.isRenamable () ||
731+ !isBackwardPropagatableRegClassCopy (Copy, *SrcUser,
732+ MO.getOperandNo ()))
733+ return false ;
734+ }
735+ }
736+ return true ;
737+ }
738+ // EraVM local end
739+
670740// / Look for available copies whose destination register is used by \p MI and
671741// / replace the use in \p MI with the copy's source register.
672742void MachineCopyPropagation::forwardUses (MachineInstr &MI) {
@@ -1036,13 +1106,29 @@ void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
10361106 if (hasOverlappingMultipleDef (MI, MODef, Def))
10371107 continue ;
10381108
1109+ // EraVM local begin
1110+ if (!canUpdateSrcUsers (*Copy, *CopyOperands->Source ))
1111+ continue ;
1112+ // EraVM local end
1113+
10391114 LLVM_DEBUG (dbgs () << " MCP: Replacing " << printReg (MODef.getReg (), TRI)
10401115 << " \n with " << printReg (Def, TRI) << " \n in "
10411116 << MI << " from " << *Copy);
10421117
10431118 MODef.setReg (Def);
10441119 MODef.setIsRenamable (CopyOperands->Destination ->isRenamable ());
10451120
1121+ // EraVM local begin
1122+ for (auto *SrcUser : Tracker.getSrcUsers (Src, *TRI)) {
1123+ for (MachineOperand &MO : SrcUser->uses ()) {
1124+ if (!MO.isReg () || !MO.isUse () || MO.getReg () != Src)
1125+ continue ;
1126+ MO.setReg (Def);
1127+ MO.setIsRenamable (CopyOperands->Destination ->isRenamable ());
1128+ }
1129+ }
1130+ // EraVM local end
1131+
10461132 LLVM_DEBUG (dbgs () << " MCP: After replacement: " << MI << " \n " );
10471133 MaybeDeadCopies.insert (Copy);
10481134 Changed = true ;
@@ -1108,7 +1194,11 @@ void MachineCopyPropagation::BackwardCopyPropagateBlock(
11081194 CopyDbgUsers[Copy].insert (&MI);
11091195 }
11101196 }
1111- } else {
1197+ // EraVM local begin
1198+ } else if (!Tracker.trackSrcUsers (MO.getReg ().asMCReg (), MI, *TRI, *TII,
1199+ UseCopyInstr)) {
1200+ // If we can't track the source users, invalidate the register.
1201+ // EraVM local end
11121202 Tracker.invalidateRegister (MO.getReg ().asMCReg (), *TRI, *TII,
11131203 UseCopyInstr);
11141204 }
0 commit comments