Skip to content

Commit f76ffc1

Browse files
committed
[MCP] Invalidate copy for super register in copy source
We must also track the super sources of a copy, otherwise we introduce a sort of subtle bug. Consider: 1. DEF r0:r1 2. USE r1 3. r6:r9 = COPY r10:r13 4. r14:15 = COPY r0:r1 5. USE r6 6.. r1:4 = COPY r6:9 BackwardCopyPropagateBlock processes the instructions from bottom up. After processing 6., we will have propagatable copy for r1-r4 and r6-r9. After 5., we invalidate and erase the propagatble copy for r1-r4 and r6 but not for r7-r9. The issue is that when processing 3., data structures still say we have valid copies for dest regs r7-r9 (from 6.). The corresponding defs for these registers in 6. are r1:r4, which we mark as registers to invalidate. When invalidating, we find the copy that corresponds to r1 is 4. (this was added when processing 4.), and we say that r1 now maps to unpropagatable copies. Thus, when we process 2., we do not have a valid copy, but when we process 1. we do -- because the mapped copy for subregister r0 was never invalidated. The net result is to propagate the copy from 4. to 1., and replace DEF r0:r1 with DEF r14:r15. Then, we have a use before def in 2. The main issue is that we have an inconsitent state between which def regs and which src regs are valid. When processing 5., we mark all the defs in 6. as invalid, but only the subreg use as invalid. Either we must only invalidate the individual subreg for both uses and defs, or the super register for both. Differential Revision: https://reviews.llvm.org//D157564 Change-Id: I99d5e0b1a0d735e8ea3bd7d137b6464690aa9486
1 parent d0e54e3 commit f76ffc1

File tree

2 files changed

+46
-17
lines changed

2 files changed

+46
-17
lines changed

llvm/lib/CodeGen/MachineCopyPropagation.cpp

+20-17
Original file line numberDiff line numberDiff line change
@@ -134,28 +134,31 @@ class CopyTracker {
134134
const TargetInstrInfo &TII, bool UseCopyInstr) {
135135
// Since Reg might be a subreg of some registers, only invalidate Reg is not
136136
// enough. We have to find the COPY defines Reg or registers defined by Reg
137-
// and invalidate all of them.
138-
SmallSet<MCRegister, 8> RegsToInvalidate;
139-
RegsToInvalidate.insert(Reg);
137+
// and invalidate all of them. Similarly, we must invalidate all of the
138+
// the subregisters used in the source of the COPY.
139+
SmallSet<MCRegUnit, 8> RegUnitsToInvalidate;
140+
auto InvalidateCopy = [&](MachineInstr *MI) {
141+
std::optional<DestSourcePair> CopyOperands =
142+
isCopyInstr(*MI, TII, UseCopyInstr);
143+
assert(CopyOperands && "Expect copy");
144+
145+
auto Dest = TRI.regunits(CopyOperands->Destination->getReg().asMCReg());
146+
auto Src = TRI.regunits(CopyOperands->Source->getReg().asMCReg());
147+
RegUnitsToInvalidate.insert(Dest.begin(), Dest.end());
148+
RegUnitsToInvalidate.insert(Src.begin(), Src.end());
149+
};
150+
140151
for (MCRegUnit Unit : TRI.regunits(Reg)) {
141152
auto I = Copies.find(Unit);
142153
if (I != Copies.end()) {
143-
if (MachineInstr *MI = I->second.MI) {
144-
std::optional<DestSourcePair> CopyOperands =
145-
isCopyInstr(*MI, TII, UseCopyInstr);
146-
assert(CopyOperands && "Expect copy");
147-
148-
RegsToInvalidate.insert(
149-
CopyOperands->Destination->getReg().asMCReg());
150-
RegsToInvalidate.insert(CopyOperands->Source->getReg().asMCReg());
151-
}
152-
RegsToInvalidate.insert(I->second.DefRegs.begin(),
153-
I->second.DefRegs.end());
154+
if (MachineInstr *MI = I->second.MI)
155+
InvalidateCopy(MI);
156+
if (MachineInstr *MI = I->second.LastSeenUseInCopy)
157+
InvalidateCopy(MI);
154158
}
155159
}
156-
for (MCRegister InvalidReg : RegsToInvalidate)
157-
for (MCRegUnit Unit : TRI.regunits(InvalidReg))
158-
Copies.erase(Unit);
160+
for (MCRegUnit Unit : RegUnitsToInvalidate)
161+
Copies.erase(Unit);
159162
}
160163

161164
/// Clobber a single register, removing it from the tracker's copy maps.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
2+
# RUN: llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -run-pass=machine-cp -o - %s | FileCheck %s
3+
4+
# machine copy prop should not introduce use before def
5+
---
6+
name: back_copy_block
7+
body: |
8+
bb.0:
9+
; CHECK-LABEL: name: back_copy_block
10+
; CHECK: $vgpr20_vgpr21_vgpr22_vgpr23 = IMPLICIT_DEF
11+
; CHECK-NEXT: $vgpr10_vgpr11_vgpr12_vgpr13 = IMPLICIT_DEF
12+
; CHECK-NEXT: renamable $vgpr0_vgpr1 = V_MOV_B64_e64 killed $vgpr20_vgpr21, implicit $exec
13+
; CHECK-NEXT: renamable $vgpr20 = V_MOV_B32_e32 killed $vgpr1, implicit $exec
14+
; CHECK-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = COPY renamable $vgpr10_vgpr11_vgpr12_vgpr13
15+
; CHECK-NEXT: renamable $vgpr20 = V_MOV_B32_e32 killed $vgpr6, implicit $exec
16+
; CHECK-NEXT: S_ENDPGM 0, amdgpu_allvgprs
17+
$vgpr20_vgpr21_vgpr22_vgpr23 = IMPLICIT_DEF
18+
$vgpr10_vgpr11_vgpr12_vgpr13 = IMPLICIT_DEF
19+
renamable $vgpr0_vgpr1 = V_MOV_B64_e64 killed renamable $vgpr20_vgpr21, implicit $exec
20+
renamable $vgpr20 = V_MOV_B32_e32 killed renamable $vgpr1, implicit $exec
21+
renamable $vgpr6_vgpr7_vgpr8_vgpr9 = COPY killed renamable $vgpr10_vgpr11_vgpr12_vgpr13
22+
renamable $vgpr14_vgpr15 = COPY killed renamable $vgpr0_vgpr1
23+
renamable $vgpr20 = V_MOV_B32_e32 killed renamable $vgpr6, implicit $exec
24+
renamable $vgpr1_vgpr2_vgpr3_vgpr4 = COPY killed renamable $vgpr6_vgpr7_vgpr8_vgpr9
25+
S_ENDPGM 0, amdgpu_allvgprs
26+
...

0 commit comments

Comments
 (0)