@@ -110,6 +110,9 @@ class CopyTracker {
110
110
struct CopyInfo {
111
111
MachineInstr *MI = nullptr ;
112
112
MachineInstr *LastSeenUseInCopy = nullptr ;
113
+ // EraVM local begin
114
+ SmallPtrSet<MachineInstr *, 4 > SrcUsers;
115
+ // EraVM local end
113
116
SmallVector<MCRegister, 4 > DefRegs;
114
117
bool Avail = false ;
115
118
};
@@ -224,6 +227,45 @@ class CopyTracker {
224
227
}
225
228
}
226
229
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
+
227
269
// / Add this copy's registers into the tracker's copy maps.
228
270
void trackCopy (MachineInstr *MI, const TargetRegisterInfo &TRI,
229
271
const TargetInstrInfo &TII, bool UseCopyInstr) {
@@ -236,7 +278,9 @@ class CopyTracker {
236
278
237
279
// Remember Def is defined by the copy.
238
280
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
240
284
241
285
// Remember source that's copied to Def. Once it's clobbered, then
242
286
// it's no longer available for copy propagation.
@@ -427,6 +471,10 @@ class MachineCopyPropagation : public MachineFunctionPass {
427
471
bool hasImplicitOverlap (const MachineInstr &MI, const MachineOperand &Use);
428
472
bool hasOverlappingMultipleDef (const MachineInstr &MI,
429
473
const MachineOperand &MODef, Register Def);
474
+ // EraVM local begin
475
+ bool canUpdateSrcUsers (const MachineInstr &Copy,
476
+ const MachineOperand &CopySrc);
477
+ // EraVM local end
430
478
431
479
// / Candidates for deletion.
432
480
SmallSetVector<MachineInstr *, 8 > MaybeDeadCopies;
@@ -667,6 +715,28 @@ bool MachineCopyPropagation::hasOverlappingMultipleDef(
667
715
return false ;
668
716
}
669
717
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
+
670
740
// / Look for available copies whose destination register is used by \p MI and
671
741
// / replace the use in \p MI with the copy's source register.
672
742
void MachineCopyPropagation::forwardUses (MachineInstr &MI) {
@@ -1036,13 +1106,29 @@ void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
1036
1106
if (hasOverlappingMultipleDef (MI, MODef, Def))
1037
1107
continue ;
1038
1108
1109
+ // EraVM local begin
1110
+ if (!canUpdateSrcUsers (*Copy, *CopyOperands->Source ))
1111
+ continue ;
1112
+ // EraVM local end
1113
+
1039
1114
LLVM_DEBUG (dbgs () << " MCP: Replacing " << printReg (MODef.getReg (), TRI)
1040
1115
<< " \n with " << printReg (Def, TRI) << " \n in "
1041
1116
<< MI << " from " << *Copy);
1042
1117
1043
1118
MODef.setReg (Def);
1044
1119
MODef.setIsRenamable (CopyOperands->Destination ->isRenamable ());
1045
1120
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
+
1046
1132
LLVM_DEBUG (dbgs () << " MCP: After replacement: " << MI << " \n " );
1047
1133
MaybeDeadCopies.insert (Copy);
1048
1134
Changed = true ;
@@ -1108,7 +1194,11 @@ void MachineCopyPropagation::BackwardCopyPropagateBlock(
1108
1194
CopyDbgUsers[Copy].insert (&MI);
1109
1195
}
1110
1196
}
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
1112
1202
Tracker.invalidateRegister (MO.getReg ().asMCReg (), *TRI, *TII,
1113
1203
UseCopyInstr);
1114
1204
}
0 commit comments