-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[MCP] Handle iterative simplification during forward copy prop #140267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -870,12 +870,6 @@ void MachineCopyPropagation::forwardUses(MachineInstr &MI) { | |
++NumCopyForwards; | ||
Changed = true; | ||
} | ||
// Attempt to canonicalize/optimize the instruction now its arguments have | ||
// been mutated. | ||
if (TII->simplifyInstruction(MI)) { | ||
Changed = true; | ||
LLVM_DEBUG(dbgs() << "MCP: After optimizeInstruction: " << MI); | ||
} | ||
} | ||
|
||
void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { | ||
|
@@ -887,10 +881,8 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { | |
std::optional<DestSourcePair> CopyOperands = | ||
isCopyInstr(MI, *TII, UseCopyInstr); | ||
if (CopyOperands) { | ||
|
||
Register RegSrc = CopyOperands->Source->getReg(); | ||
Register RegDef = CopyOperands->Destination->getReg(); | ||
|
||
if (!TRI->regsOverlap(RegDef, RegSrc)) { | ||
assert(RegDef.isPhysical() && RegSrc.isPhysical() && | ||
"MachineCopyPropagation should be run after register allocation!"); | ||
|
@@ -915,51 +907,6 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { | |
// %ecx = COPY %eax | ||
if (eraseIfRedundant(MI, Def, Src) || eraseIfRedundant(MI, Src, Def)) | ||
continue; | ||
|
||
forwardUses(MI); | ||
|
||
// Src may have been changed by forwardUses() | ||
CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr); | ||
Src = CopyOperands->Source->getReg().asMCReg(); | ||
|
||
// If Src is defined by a previous copy, the previous copy cannot be | ||
// eliminated. | ||
ReadRegister(Src, MI, RegularUse); | ||
for (const MachineOperand &MO : MI.implicit_operands()) { | ||
if (!MO.isReg() || !MO.readsReg()) | ||
continue; | ||
MCRegister Reg = MO.getReg().asMCReg(); | ||
if (!Reg) | ||
continue; | ||
ReadRegister(Reg, MI, RegularUse); | ||
} | ||
|
||
LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI.dump()); | ||
|
||
// Copy is now a candidate for deletion. | ||
if (!MRI->isReserved(Def)) | ||
MaybeDeadCopies.insert(&MI); | ||
|
||
// If 'Def' is previously source of another copy, then this earlier copy's | ||
// source is no longer available. e.g. | ||
// %xmm9 = copy %xmm2 | ||
// ... | ||
// %xmm2 = copy %xmm0 | ||
// ... | ||
// %xmm2 = copy %xmm9 | ||
Tracker.clobberRegister(Def, *TRI, *TII, UseCopyInstr); | ||
for (const MachineOperand &MO : MI.implicit_operands()) { | ||
if (!MO.isReg() || !MO.isDef()) | ||
continue; | ||
MCRegister Reg = MO.getReg().asMCReg(); | ||
if (!Reg) | ||
continue; | ||
Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr); | ||
} | ||
|
||
Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr); | ||
|
||
continue; | ||
} | ||
} | ||
|
||
|
@@ -977,20 +924,36 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { | |
|
||
forwardUses(MI); | ||
|
||
// It's possible that the previous transformation has resulted in a no-op | ||
// register move (i.e. one where source and destination registers are the | ||
// same and are not referring to a reserved register). If so, delete it. | ||
CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr); | ||
if (CopyOperands && | ||
CopyOperands->Source->getReg() == CopyOperands->Destination->getReg() && | ||
!MRI->isReserved(CopyOperands->Source->getReg())) { | ||
MI.eraseFromParent(); | ||
NumDeletes++; | ||
// Attempt to canonicalize/optimize the instruction now its arguments have | ||
// been mutated. This may convert MI from a non-copy to a copy instruction. | ||
if (TII->simplifyInstruction(MI)) { | ||
Changed = true; | ||
continue; | ||
LLVM_DEBUG(dbgs() << "MCP: After simplifyInstruction: " << MI); | ||
} | ||
|
||
CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr); | ||
if (CopyOperands) { | ||
Register RegSrc = CopyOperands->Source->getReg(); | ||
Register RegDef = CopyOperands->Destination->getReg(); | ||
// It's possible that the previous transformations have resulted in a | ||
// no-op register move (i.e. one where source and destination registers | ||
// are the same and are not referring to a reserved register). If so, | ||
// delete it. | ||
if (RegSrc == RegDef && !MRI->isReserved(RegSrc)) { | ||
MI.eraseFromParent(); | ||
NumDeletes++; | ||
Changed = true; | ||
continue; | ||
} | ||
|
||
if (!TRI->regsOverlap(RegDef, RegSrc)) { | ||
// Copy is now a candidate for deletion. | ||
MCRegister Def = RegDef.asMCReg(); | ||
if (!MRI->isReserved(Def)) | ||
MaybeDeadCopies.insert(&MI); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, off topic, possible follow up. Looking at this code, it really looks like we have a nearly generic DCE lurking here. For a general instruction (not just copies), we could track if a def is used. If not and the instruction is safe to delete, we could do so. Not sure how worthwhile this is, but interesting. |
||
} | ||
} | ||
|
||
// Not a copy. | ||
SmallVector<Register, 4> Defs; | ||
const MachineOperand *RegMask = nullptr; | ||
for (const MachineOperand &MO : MI.operands()) { | ||
|
@@ -1070,6 +1033,14 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { | |
// Any previous copy definition or reading the Defs is no longer available. | ||
for (MCRegister Reg : Defs) | ||
Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr); | ||
|
||
if (CopyOperands) { | ||
Register RegSrc = CopyOperands->Source->getReg(); | ||
Register RegDef = CopyOperands->Destination->getReg(); | ||
if (!TRI->regsOverlap(RegDef, RegSrc)) { | ||
Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr); | ||
} | ||
} | ||
} | ||
|
||
bool TracksLiveness = MRI->tracksLiveness(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slightly OT for this review, but I think the eraseIfRedundant case could be removed. The key thing it does which the main copy propagation doesn't is reason about super-registers updating sub-registers in known ways. We could generalize the main pass, and I think this code would become redundant. I may explore this further, or may not.