@@ -109,6 +109,9 @@ class CopyTracker {
109109 struct CopyInfo {
110110 MachineInstr *MI = nullptr ;
111111 MachineInstr *LastSeenUseInCopy = nullptr ;
112+ // EraVM local begin
113+ SmallPtrSet<MachineInstr *, 4 > SrcUsers;
114+ // EraVM local end
112115 SmallVector<MCRegister, 4 > DefRegs;
113116 bool Avail = false ;
114117 };
@@ -182,6 +185,45 @@ class CopyTracker {
182185 }
183186 }
184187
188+ // EraVM local begin
189+ // / Track copy's src users, and return false if that can't be done.
190+ // / We can only track if we have a COPY instruction which source is
191+ // / the same as the Reg.
192+ bool trackSrcUsers (MCRegister Reg, MachineInstr &MI,
193+ const TargetRegisterInfo &TRI, const TargetInstrInfo &TII,
194+ bool UseCopyInstr) {
195+ MCRegUnit RU = *TRI.regunits (Reg).begin ();
196+ MachineInstr *AvailCopy = findCopyDefViaUnit (RU, TRI);
197+ if (!AvailCopy)
198+ return false ;
199+
200+ std::optional<DestSourcePair> CopyOperands =
201+ isCopyInstr (*AvailCopy, TII, UseCopyInstr);
202+ Register Src = CopyOperands->Source ->getReg ();
203+
204+ // Bail out, if the source of the copy is not the same as the Reg.
205+ if (Src != Reg)
206+ return false ;
207+
208+ auto I = Copies.find (RU);
209+ if (I == Copies.end ())
210+ return false ;
211+
212+ I->second .SrcUsers .insert (&MI);
213+ return true ;
214+ }
215+
216+ // / Return the users for a given register.
217+ SmallPtrSet<MachineInstr *, 4 > getSrcUsers (MCRegister Reg,
218+ const TargetRegisterInfo &TRI) {
219+ MCRegUnit RU = *TRI.regunits (Reg).begin ();
220+ auto I = Copies.find (RU);
221+ if (I == Copies.end ())
222+ return {};
223+ return I->second .SrcUsers ;
224+ }
225+ // EraVM local end
226+
185227 // / Add this copy's registers into the tracker's copy maps.
186228 void trackCopy (MachineInstr *MI, const TargetRegisterInfo &TRI,
187229 const TargetInstrInfo &TII, bool UseCopyInstr) {
@@ -194,7 +236,9 @@ class CopyTracker {
194236
195237 // Remember Def is defined by the copy.
196238 for (MCRegUnit Unit : TRI.regunits (Def))
197- Copies[Unit] = {MI, nullptr , {}, true };
239+ // EraVM local begin
240+ Copies[Unit] = {MI, nullptr , {}, {}, true };
241+ // EraVM local end
198242
199243 // Remember source that's copied to Def. Once it's clobbered, then
200244 // it's no longer available for copy propagation.
@@ -385,6 +429,10 @@ class MachineCopyPropagation : public MachineFunctionPass {
385429 bool hasImplicitOverlap (const MachineInstr &MI, const MachineOperand &Use);
386430 bool hasOverlappingMultipleDef (const MachineInstr &MI,
387431 const MachineOperand &MODef, Register Def);
432+ // EraVM local begin
433+ bool canUpdateSrcUsers (const MachineInstr &Copy,
434+ const MachineOperand &CopySrc);
435+ // EraVM local end
388436
389437 // / Candidates for deletion.
390438 SmallSetVector<MachineInstr *, 8 > MaybeDeadCopies;
@@ -625,6 +673,28 @@ bool MachineCopyPropagation::hasOverlappingMultipleDef(
625673 return false ;
626674}
627675
676+ // EraVM local begin
677+ // / Return true if it is safe to update the users of the source register of the
678+ // / copy.
679+ bool MachineCopyPropagation::canUpdateSrcUsers (const MachineInstr &Copy,
680+ const MachineOperand &CopySrc) {
681+ for (auto *SrcUser : Tracker.getSrcUsers (CopySrc.getReg (), *TRI)) {
682+ if (hasImplicitOverlap (*SrcUser, CopySrc))
683+ return false ;
684+
685+ for (MachineOperand &MO : SrcUser->uses ()) {
686+ if (!MO.isReg () || !MO.isUse () || MO.getReg () != CopySrc.getReg ())
687+ continue ;
688+ if (MO.isTied () || !MO.isRenamable () ||
689+ !isBackwardPropagatableRegClassCopy (Copy, *SrcUser,
690+ MO.getOperandNo ()))
691+ return false ;
692+ }
693+ }
694+ return true ;
695+ }
696+ // EraVM local end
697+
628698// / Look for available copies whose destination register is used by \p MI and
629699// / replace the use in \p MI with the copy's source register.
630700void MachineCopyPropagation::forwardUses (MachineInstr &MI) {
@@ -995,13 +1065,29 @@ void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
9951065 if (hasOverlappingMultipleDef (MI, MODef, Def))
9961066 continue ;
9971067
1068+ // EraVM local begin
1069+ if (!canUpdateSrcUsers (*Copy, *CopyOperands->Source ))
1070+ continue ;
1071+ // EraVM local end
1072+
9981073 LLVM_DEBUG (dbgs () << " MCP: Replacing " << printReg (MODef.getReg (), TRI)
9991074 << " \n with " << printReg (Def, TRI) << " \n in "
10001075 << MI << " from " << *Copy);
10011076
10021077 MODef.setReg (Def);
10031078 MODef.setIsRenamable (CopyOperands->Destination ->isRenamable ());
10041079
1080+ // EraVM local begin
1081+ for (auto *SrcUser : Tracker.getSrcUsers (Src, *TRI)) {
1082+ for (MachineOperand &MO : SrcUser->uses ()) {
1083+ if (!MO.isReg () || !MO.isUse () || MO.getReg () != Src)
1084+ continue ;
1085+ MO.setReg (Def);
1086+ MO.setIsRenamable (CopyOperands->Destination ->isRenamable ());
1087+ }
1088+ }
1089+ // EraVM local end
1090+
10051091 LLVM_DEBUG (dbgs () << " MCP: After replacement: " << MI << " \n " );
10061092 MaybeDeadCopies.insert (Copy);
10071093 Changed = true ;
@@ -1067,7 +1153,11 @@ void MachineCopyPropagation::BackwardCopyPropagateBlock(
10671153 CopyDbgUsers[Copy].insert (&MI);
10681154 }
10691155 }
1070- } else {
1156+ // EraVM local begin
1157+ } else if (!Tracker.trackSrcUsers (MO.getReg ().asMCReg (), MI, *TRI, *TII,
1158+ UseCopyInstr)) {
1159+ // If we can't track the source users, invalidate the register.
1160+ // EraVM local end
10711161 Tracker.invalidateRegister (MO.getReg ().asMCReg (), *TRI, *TII,
10721162 UseCopyInstr);
10731163 }
0 commit comments