@@ -164,67 +164,91 @@ class CopyTracker {
164164 Copies.erase (Unit);
165165 }
166166
167- // / Clobber a single register, removing it from the tracker's copy maps.
168- void clobberRegister (MCRegister Reg, const TargetRegisterInfo &TRI,
169- const TargetInstrInfo &TII, bool UseCopyInstr) {
170- for (MCRegUnit Unit : TRI.regunits (Reg)) {
171- auto I = Copies.find (Unit);
172- if (I != Copies.end ()) {
173- // When we clobber the source of a copy, we need to clobber everything
174- // it defined.
175- markRegsUnavailable (I->second .DefRegs , TRI);
176- // When we clobber the destination of a copy, we need to clobber the
177- // whole register it defined.
178- if (MachineInstr *MI = I->second .MI ) {
179- std::optional<DestSourcePair> CopyOperands =
180- isCopyInstr (*MI, TII, UseCopyInstr);
181-
182- MCRegister Def = CopyOperands->Destination ->getReg ().asMCReg ();
183- MCRegister Src = CopyOperands->Source ->getReg ().asMCReg ();
184-
185- markRegsUnavailable (Def, TRI);
186-
187- // Since we clobber the destination of a copy, the semantic of Src's
188- // "DefRegs" to contain Def is no longer effectual. We will also need
189- // to remove the record from the copy maps that indicates Src defined
190- // Def. Failing to do so might cause the target to miss some
191- // opportunities to further eliminate redundant copy instructions.
192- // Consider the following sequence during the
193- // ForwardCopyPropagateBlock procedure:
194- // L1: r0 = COPY r9 <- TrackMI
195- // L2: r0 = COPY r8 <- TrackMI (Remove r9 defined r0 from tracker)
196- // L3: use r0 <- Remove L2 from MaybeDeadCopies
197- // L4: early-clobber r9 <- Clobber r9 (L2 is still valid in tracker)
198- // L5: r0 = COPY r8 <- Remove NopCopy
199- for (MCRegUnit SrcUnit : TRI.regunits (Src)) {
200- auto SrcCopy = Copies.find (SrcUnit);
201- if (SrcCopy != Copies.end () && SrcCopy->second .LastSeenUseInCopy ) {
202- // If SrcCopy defines multiple values, we only need
203- // to erase the record for Def in DefRegs.
204- for (auto itr = SrcCopy->second .DefRegs .begin ();
205- itr != SrcCopy->second .DefRegs .end (); itr++) {
206- if (*itr == Def) {
207- SrcCopy->second .DefRegs .erase (itr);
208- // If DefReg becomes empty after removal, we can remove the
209- // SrcCopy from the tracker's copy maps. We only remove those
210- // entries solely record the Def is defined by Src. If an
211- // entry also contains the definition record of other Def'
212- // registers, it cannot be cleared.
213- if (SrcCopy->second .DefRegs .empty () && !SrcCopy->second .MI ) {
214- Copies.erase (SrcCopy);
215- }
216- break ;
167+ // / Clobber a single register unit, removing it from the tracker's copy maps.
168+ void clobberRegUnit (MCRegUnit Unit, const TargetRegisterInfo &TRI,
169+ const TargetInstrInfo &TII, bool UseCopyInstr) {
170+ auto I = Copies.find (Unit);
171+ if (I != Copies.end ()) {
172+ // When we clobber the source of a copy, we need to clobber everything
173+ // it defined.
174+ markRegsUnavailable (I->second .DefRegs , TRI);
175+ // When we clobber the destination of a copy, we need to clobber the
176+ // whole register it defined.
177+ if (MachineInstr *MI = I->second .MI ) {
178+ std::optional<DestSourcePair> CopyOperands =
179+ isCopyInstr (*MI, TII, UseCopyInstr);
180+
181+ MCRegister Def = CopyOperands->Destination ->getReg ().asMCReg ();
182+ MCRegister Src = CopyOperands->Source ->getReg ().asMCReg ();
183+
184+ markRegsUnavailable (Def, TRI);
185+
186+ // Since we clobber the destination of a copy, the semantic of Src's
187+ // "DefRegs" to contain Def is no longer effectual. We will also need
188+ // to remove the record from the copy maps that indicates Src defined
189+ // Def. Failing to do so might cause the target to miss some
190+ // opportunities to further eliminate redundant copy instructions.
191+ // Consider the following sequence during the
192+ // ForwardCopyPropagateBlock procedure:
193+ // L1: r0 = COPY r9 <- TrackMI
194+ // L2: r0 = COPY r8 <- TrackMI (Remove r9 defined r0 from tracker)
195+ // L3: use r0 <- Remove L2 from MaybeDeadCopies
196+ // L4: early-clobber r9 <- Clobber r9 (L2 is still valid in tracker)
197+ // L5: r0 = COPY r8 <- Remove NopCopy
198+ for (MCRegUnit SrcUnit : TRI.regunits (Src)) {
199+ auto SrcCopy = Copies.find (SrcUnit);
200+ if (SrcCopy != Copies.end () && SrcCopy->second .LastSeenUseInCopy ) {
201+ // If SrcCopy defines multiple values, we only need
202+ // to erase the record for Def in DefRegs.
203+ for (auto itr = SrcCopy->second .DefRegs .begin ();
204+ itr != SrcCopy->second .DefRegs .end (); itr++) {
205+ if (*itr == Def) {
206+ SrcCopy->second .DefRegs .erase (itr);
207+ // If DefReg becomes empty after removal, we can remove the
208+ // SrcCopy from the tracker's copy maps. We only remove those
209+ // entries solely record the Def is defined by Src. If an
210+ // entry also contains the definition record of other Def'
211+ // registers, it cannot be cleared.
212+ if (SrcCopy->second .DefRegs .empty () && !SrcCopy->second .MI ) {
213+ Copies.erase (SrcCopy);
217214 }
215+ break ;
218216 }
219217 }
220218 }
221219 }
222- // Now we can erase the copy.
223- Copies.erase (I);
224220 }
221+ // Now we can erase the copy.
222+ Copies.erase (I);
225223 }
226224 }
227225
226+ // / Clobber a single register, removing it from the tracker's copy maps.
227+ void clobberRegister (MCRegister Reg, const TargetRegisterInfo &TRI,
228+ const TargetInstrInfo &TII, bool UseCopyInstr) {
229+ for (MCRegUnit Unit : TRI.regunits (Reg)) {
230+ clobberRegUnit (Unit, TRI, TII, UseCopyInstr);
231+ }
232+ }
233+
234+ // / Clobber all registers which are not preserved by RegMask, removing them
235+ // / from the tracker's copy maps.
236+ void clobberRegistersExceptMask (const MachineOperand *RegMask,
237+ const TargetRegisterInfo &TRI,
238+ const TargetInstrInfo &TII,
239+ bool UseCopyInstr) {
240+ BitVector SafeRegUnits (TRI.getNumRegUnits ());
241+
242+ for (unsigned SafeReg = 0 , E = TRI.getNumRegs (); SafeReg < E; ++SafeReg)
243+ if (!RegMask->clobbersPhysReg (SafeReg))
244+ for (auto SafeUnit : TRI.regunits (SafeReg))
245+ SafeRegUnits.set (SafeUnit);
246+
247+ for (unsigned Unit = 0 , E = TRI.getNumRegUnits (); Unit < E; ++Unit)
248+ if (!SafeRegUnits.test (Unit))
249+ clobberRegUnit (Unit, TRI, TII, UseCopyInstr);
250+ }
251+
228252 // / Track copy's src users, and return false if that can't be done.
229253 // / We can only track if we have a COPY instruction which source is
230254 // / the same as the Reg.
@@ -960,6 +984,10 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
960984 // a large set of registers. Treat clobbered registers the same way as
961985 // defined registers.
962986 if (RegMask) {
987+ // Invalidate all entries in the copy map which are not preserved by this
988+ // register mask.
989+ Tracker.clobberRegistersExceptMask (RegMask, *TRI, *TII, UseCopyInstr);
990+
963991 // Erase any MaybeDeadCopies whose destination register is clobbered.
964992 for (SmallSetVector<MachineInstr *, 8 >::iterator DI =
965993 MaybeDeadCopies.begin ();
@@ -978,10 +1006,6 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
9781006 LLVM_DEBUG (dbgs () << " MCP: Removing copy due to regmask clobbering: " ;
9791007 MaybeDead->dump ());
9801008
981- // Make sure we invalidate any entries in the copy maps before erasing
982- // the instruction.
983- Tracker.clobberRegister (Reg, *TRI, *TII, UseCopyInstr);
984-
9851009 // erase() will return the next valid iterator pointing to the next
9861010 // element after the erased one.
9871011 DI = MaybeDeadCopies.erase (DI);
0 commit comments