Skip to content

Commit e8e3e6e

Browse files
jofrnarsenm
andauthored
[LiveVariables] Mark use without implicit if defined at instr (#119446)
LiveVariables will mark instructions with their implicit subregister uses. However, it will also mark the subregister as an implicit if its own definition is a subregister of it, i.e. `$r3 = OP val, implicit-def $r0_r1_r2_r3, ..., implicit $r2_r3`, even if it is otherwise unused, which defines $r3 on the same line it is used. This change ensures such uses are marked without implicit, i.e. `$r3 = OP val, implicit-def $r0_r1_r2_r3, ..., $r2_r3`. --------- Co-authored-by: Matt Arsenault <[email protected]>
1 parent 6aafe65 commit e8e3e6e

File tree

5 files changed

+123
-38
lines changed

5 files changed

+123
-38
lines changed

llvm/include/llvm/CodeGen/LiveVariables.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,8 @@ class LiveVariables {
165165
MachineInstr *FindLastRefOrPartRef(Register Reg);
166166

167167
/// FindLastPartialDef - Return the last partial def of the specified
168-
/// register. Also returns the sub-registers that're defined by the
169-
/// instruction.
170-
MachineInstr *FindLastPartialDef(Register Reg,
171-
SmallSet<Register, 4> &PartDefRegs);
168+
/// register.
169+
MachineInstr *FindLastPartialDef(Register Reg);
172170

173171
/// analyzePHINodes - Gather information about the PHI nodes in here. In
174172
/// particular, we want to map the variable information of a virtual

llvm/lib/CodeGen/LiveVariables.cpp

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,7 @@ void LiveVariables::HandleVirtRegDef(Register Reg, MachineInstr &MI) {
213213
}
214214

215215
/// FindLastPartialDef - Return the last partial def of the specified register.
216-
/// Also returns the sub-registers that're defined by the instruction.
217-
MachineInstr *
218-
LiveVariables::FindLastPartialDef(Register Reg,
219-
SmallSet<Register, 4> &PartDefRegs) {
220-
Register LastDefReg = 0;
216+
MachineInstr *LiveVariables::FindLastPartialDef(Register Reg) {
221217
unsigned LastDefDist = 0;
222218
MachineInstr *LastDef = nullptr;
223219
for (MCPhysReg SubReg : TRI->subregs(Reg)) {
@@ -226,7 +222,6 @@ LiveVariables::FindLastPartialDef(Register Reg,
226222
continue;
227223
unsigned Dist = DistanceMap[Def];
228224
if (Dist > LastDefDist) {
229-
LastDefReg = SubReg;
230225
LastDef = Def;
231226
LastDefDist = Dist;
232227
}
@@ -235,14 +230,6 @@ LiveVariables::FindLastPartialDef(Register Reg,
235230
if (!LastDef)
236231
return nullptr;
237232

238-
PartDefRegs.insert(LastDefReg);
239-
for (MachineOperand &MO : LastDef->all_defs()) {
240-
if (MO.getReg() == 0)
241-
continue;
242-
Register DefReg = MO.getReg();
243-
if (TRI->isSubRegister(Reg, DefReg))
244-
PartDefRegs.insert_range(TRI->subregs_inclusive(DefReg));
245-
}
246233
return LastDef;
247234
}
248235

@@ -261,27 +248,11 @@ void LiveVariables::HandlePhysRegUse(Register Reg, MachineInstr &MI) {
261248
// ...
262249
// = EAX
263250
// All of the sub-registers must have been defined before the use of Reg!
264-
SmallSet<Register, 4> PartDefRegs;
265-
MachineInstr *LastPartialDef = FindLastPartialDef(Reg, PartDefRegs);
251+
MachineInstr *LastPartialDef = FindLastPartialDef(Reg);
266252
// If LastPartialDef is NULL, it must be using a livein register.
267253
if (LastPartialDef) {
268-
LastPartialDef->addOperand(MachineOperand::CreateReg(Reg, true/*IsDef*/,
269-
true/*IsImp*/));
270-
PhysRegDef[Reg.id()] = LastPartialDef;
271-
SmallSet<MCPhysReg, 8> Processed;
272-
for (MCPhysReg SubReg : TRI->subregs(Reg)) {
273-
if (Processed.count(SubReg))
274-
continue;
275-
if (PartDefRegs.count(SubReg))
276-
continue;
277-
// This part of Reg was defined before the last partial def. It's killed
278-
// here.
279-
LastPartialDef->addOperand(MachineOperand::CreateReg(SubReg,
280-
false/*IsDef*/,
281-
true/*IsImp*/));
282-
PhysRegDef[SubReg] = LastPartialDef;
283-
Processed.insert_range(TRI->subregs(SubReg));
284-
}
254+
LastPartialDef->addOperand(
255+
MachineOperand::CreateReg(Reg, /*IsDef=*/true, /*IsImp=*/true));
285256
}
286257
} else if (LastDef && !PhysRegUse[Reg.id()] &&
287258
!LastDef->findRegisterDefOperand(Reg, /*TRI=*/nullptr))

llvm/test/CodeGen/AArch64/ldrpre-ldr-merge.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ body: |
756756
; CHECK: liveins: $x0, $x1, $x2
757757
; CHECK-NEXT: {{ $}}
758758
; CHECK-NEXT: early-clobber renamable $x1, renamable $x0 = LDRSWpre renamable $x1, 40, implicit $w1, implicit $w1_hi :: (load (s32))
759-
; CHECK-NEXT: renamable $w2 = LDRWui renamable $x1, 1, implicit-def $x2, implicit $w2_hi :: (load (s32))
759+
; CHECK-NEXT: renamable $w2 = LDRWui renamable $x1, 1, implicit-def $x2 :: (load (s32))
760760
; CHECK-NEXT: STPXi renamable $x0, renamable $x2, renamable $x1, 0 :: (store (s64))
761761
; CHECK-NEXT: RET undef $lr
762762
early-clobber renamable $x1, renamable $x0 = LDRSWpre killed renamable $x1, 40 :: (load (s32))
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=amdgcn-amd-amdpal -mcpu=gfx900 -O1 %s -o - | FileCheck %s
3+
4+
define amdgpu_ps <4 x float> @caller(ptr %ptr) {
5+
; CHECK-LABEL: caller:
6+
; CHECK: ; %bb.0:
7+
; CHECK-NEXT: flat_load_dword v1, v[0:1]
8+
; CHECK-NEXT: s_mov_b32 s0, 0
9+
; CHECK-NEXT: s_mov_b32 s1, 0
10+
; CHECK-NEXT: s_mov_b32 s2, 0
11+
; CHECK-NEXT: s_mov_b32 s5, fn@abs32@hi
12+
; CHECK-NEXT: s_mov_b32 s4, fn@abs32@lo
13+
; CHECK-NEXT: s_mov_b64 s[8:9], 0
14+
; CHECK-NEXT: v_mov_b32_e32 v0, 0
15+
; CHECK-NEXT: s_mov_b32 s3, 0
16+
; CHECK-NEXT: v_mov_b32_e32 v2, 0
17+
; CHECK-NEXT: s_mov_b32 s32, 0
18+
; CHECK-NEXT: s_swappc_b64 s[30:31], s[4:5]
19+
; CHECK-NEXT: ; return to shader part epilog
20+
%L = load i32, ptr %ptr, align 4
21+
%R = call <4 x float> @fn(<4 x i32> zeroinitializer, i32 0, i32 %L, i32 0)
22+
ret <4 x float> %R
23+
}
24+
25+
declare hidden <4 x float> @fn(<4 x i32> inreg, i32, i32, i32)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple=amdgcn --run-pass=livevars -o - %s | FileCheck %s
3+
---
4+
# Check that super register is defined for an sgpr copy.
5+
name: sgpr_copy
6+
tracksRegLiveness: true
7+
body: |
8+
bb.0:
9+
10+
; CHECK-LABEL: name: sgpr_copy
11+
; CHECK: %sval:sreg_32 = S_MOV_B32 0
12+
; CHECK-NEXT: $sgpr0 = COPY %sval
13+
; CHECK-NEXT: $sgpr1 = COPY %sval
14+
; CHECK-NEXT: $sgpr2 = COPY %sval
15+
; CHECK-NEXT: $sgpr3 = COPY killed %sval
16+
; CHECK-NEXT: SI_RETURN implicit killed $sgpr0_sgpr1_sgpr2_sgpr3
17+
%sval:sreg_32 = S_MOV_B32 0
18+
19+
$sgpr0 = COPY %sval
20+
$sgpr1 = COPY %sval
21+
$sgpr2 = COPY %sval
22+
$sgpr3 = COPY %sval
23+
SI_RETURN implicit $sgpr0_sgpr1_sgpr2_sgpr3
24+
25+
...
26+
---
27+
# Check that super register is defined for a vgpr vector copy.
28+
name: vgpr_copy
29+
tracksRegLiveness: true
30+
body: |
31+
bb.0:
32+
33+
; CHECK-LABEL: name: vgpr_copy
34+
; CHECK: %vval:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
35+
; CHECK-NEXT: $vgpr0 = COPY %vval
36+
; CHECK-NEXT: $vgpr1 = COPY %vval
37+
; CHECK-NEXT: $vgpr2 = COPY %vval
38+
; CHECK-NEXT: $vgpr3 = COPY killed %vval
39+
; CHECK-NEXT: dead [[COPY:%[0-9]+]]:vgpr_32 = COPY killed $vgpr0_vgpr1_vgpr2_vgpr3
40+
%vval:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
41+
42+
$vgpr0 = COPY %vval
43+
$vgpr1 = COPY %vval
44+
$vgpr2 = COPY %vval
45+
$vgpr3 = COPY %vval
46+
%0:vgpr_32 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
47+
48+
...
49+
---
50+
# Check that super register is defined when there is a hole.
51+
name: sgpr_copy_hole
52+
tracksRegLiveness: true
53+
body: |
54+
bb.0:
55+
; CHECK-LABEL: name: sgpr_copy_hole
56+
; CHECK: %sval:sreg_32 = S_MOV_B32 0
57+
; CHECK-NEXT: $sgpr0 = COPY %sval
58+
; CHECK-NEXT: $sgpr2 = COPY %sval
59+
; CHECK-NEXT: $sgpr3 = COPY killed %sval
60+
; CHECK-NEXT: SI_RETURN implicit killed $sgpr0_sgpr1_sgpr2_sgpr3
61+
%sval:sreg_32 = S_MOV_B32 0
62+
63+
$sgpr0 = COPY %sval
64+
$sgpr2 = COPY %sval
65+
$sgpr3 = COPY %sval
66+
SI_RETURN implicit $sgpr0_sgpr1_sgpr2_sgpr3
67+
68+
...
69+
---
70+
# Check that super register is defined when a pair interrupts the sequence.
71+
name: vgpr_copy_pair
72+
tracksRegLiveness: true
73+
body: |
74+
bb.0:
75+
; CHECK-LABEL: name: vgpr_copy_pair
76+
; CHECK: %vval:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
77+
; CHECK-NEXT: $vgpr0 = COPY %vval
78+
; CHECK-NEXT: $vgpr1 = COPY %vval
79+
; CHECK-NEXT: $vgpr2 = COPY %vval
80+
; CHECK-NEXT: $vgpr3 = COPY killed %vval
81+
; CHECK-NEXT: dead [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr1_vgpr2
82+
; CHECK-NEXT: dead [[COPY1:%[0-9]+]]:vgpr_32 = COPY killed $vgpr0_vgpr1_vgpr2_vgpr3
83+
%vval:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
84+
85+
$vgpr0 = COPY %vval
86+
$vgpr1 = COPY %vval
87+
$vgpr2 = COPY %vval
88+
$vgpr3 = COPY %vval
89+
%0:vgpr_32 = COPY $vgpr1_vgpr2
90+
%1:vgpr_32 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
91+
...

0 commit comments

Comments
 (0)