@@ -109,6 +109,9 @@ class CopyTracker {
109
109
struct CopyInfo {
110
110
MachineInstr *MI = nullptr ;
111
111
MachineInstr *LastSeenUseInCopy = nullptr ;
112
+ // EraVM local begin
113
+ SmallPtrSet<MachineInstr *, 4 > SrcUsers;
114
+ // EraVM local end
112
115
SmallVector<MCRegister, 4 > DefRegs;
113
116
bool Avail = false ;
114
117
};
@@ -182,6 +185,45 @@ class CopyTracker {
182
185
}
183
186
}
184
187
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
+
185
227
// / Add this copy's registers into the tracker's copy maps.
186
228
void trackCopy (MachineInstr *MI, const TargetRegisterInfo &TRI,
187
229
const TargetInstrInfo &TII, bool UseCopyInstr) {
@@ -194,7 +236,9 @@ class CopyTracker {
194
236
195
237
// Remember Def is defined by the copy.
196
238
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
198
242
199
243
// Remember source that's copied to Def. Once it's clobbered, then
200
244
// it's no longer available for copy propagation.
@@ -385,6 +429,10 @@ class MachineCopyPropagation : public MachineFunctionPass {
385
429
bool hasImplicitOverlap (const MachineInstr &MI, const MachineOperand &Use);
386
430
bool hasOverlappingMultipleDef (const MachineInstr &MI,
387
431
const MachineOperand &MODef, Register Def);
432
+ // EraVM local begin
433
+ bool canUpdateSrcUsers (const MachineInstr &Copy,
434
+ const MachineOperand &CopySrc);
435
+ // EraVM local end
388
436
389
437
// / Candidates for deletion.
390
438
SmallSetVector<MachineInstr *, 8 > MaybeDeadCopies;
@@ -625,6 +673,28 @@ bool MachineCopyPropagation::hasOverlappingMultipleDef(
625
673
return false ;
626
674
}
627
675
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
+
628
698
// / Look for available copies whose destination register is used by \p MI and
629
699
// / replace the use in \p MI with the copy's source register.
630
700
void MachineCopyPropagation::forwardUses (MachineInstr &MI) {
@@ -995,13 +1065,29 @@ void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
995
1065
if (hasOverlappingMultipleDef (MI, MODef, Def))
996
1066
continue ;
997
1067
1068
+ // EraVM local begin
1069
+ if (!canUpdateSrcUsers (*Copy, *CopyOperands->Source ))
1070
+ continue ;
1071
+ // EraVM local end
1072
+
998
1073
LLVM_DEBUG (dbgs () << " MCP: Replacing " << printReg (MODef.getReg (), TRI)
999
1074
<< " \n with " << printReg (Def, TRI) << " \n in "
1000
1075
<< MI << " from " << *Copy);
1001
1076
1002
1077
MODef.setReg (Def);
1003
1078
MODef.setIsRenamable (CopyOperands->Destination ->isRenamable ());
1004
1079
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
+
1005
1091
LLVM_DEBUG (dbgs () << " MCP: After replacement: " << MI << " \n " );
1006
1092
MaybeDeadCopies.insert (Copy);
1007
1093
Changed = true ;
@@ -1067,7 +1153,11 @@ void MachineCopyPropagation::BackwardCopyPropagateBlock(
1067
1153
CopyDbgUsers[Copy].insert (&MI);
1068
1154
}
1069
1155
}
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
1071
1161
Tracker.invalidateRegister (MO.getReg ().asMCReg (), *TRI, *TII,
1072
1162
UseCopyInstr);
1073
1163
}
0 commit comments