Skip to content

Commit 362d5ff

Browse files
[CodeGen] commuteInstruction should update implicit-def (#131361)
When the RegisterCoalescer adds an implicit-def when coalescing a SUBREG_TO_REG (#123632), this causes issues when removing other COPY nodes by commuting the instruction because it doesn't take the implicit-def into consideration. This PR fixes that.
1 parent f56b6ec commit 362d5ff

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

llvm/lib/CodeGen/TargetInstrInfo.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,14 @@ MachineInstr *TargetInstrInfo::commuteInstructionImpl(MachineInstr &MI,
238238
}
239239

240240
if (HasDef) {
241-
CommutedMI->getOperand(0).setReg(Reg0);
241+
// Use `substituteRegister` so that for a case like this:
242+
// %0.sub = INST %0.sub(tied), %1.sub, implicit-def %0
243+
// the implicit-def is also updated, to result in:
244+
// %1.sub = INST %1.sub(tied), %0.sub, implicit-def %1
245+
const TargetRegisterInfo &TRI =
246+
*MI.getMF()->getSubtarget().getRegisterInfo();
247+
Register FromReg = CommutedMI->getOperand(0).getReg();
248+
CommutedMI->substituteRegister(FromReg, Reg0, /*SubRegIdx=*/0, TRI);
242249
CommutedMI->getOperand(0).setSubReg(SubReg0);
243250
}
244251
CommutedMI->getOperand(Idx2).setReg(Reg1);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple=x86_64 -run-pass=register-coalescer -o - %s | FileCheck %s
3+
4+
# When the coalescer removes the COPY by commuting the operands of the AND, it should also update the `implicit-def` of the destination register.
5+
---
6+
name: implicit_def_dst
7+
tracksRegLiveness: true
8+
body: |
9+
bb.0:
10+
; CHECK-LABEL: name: implicit_def_dst
11+
; CHECK: [[MOV64rm:%[0-9]+]]:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
12+
; CHECK-NEXT: [[MOV64rm1:%[0-9]+]]:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
13+
; CHECK-NEXT: [[MOV64rm:%[0-9]+]].sub_32bit:gr64_with_sub_8bit = AND32rr [[MOV64rm]].sub_32bit, [[MOV64rm1]].sub_32bit, implicit-def dead $eflags, implicit-def [[MOV64rm]]
14+
; CHECK-NEXT: RET 0, implicit [[MOV64rm]]
15+
%0:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
16+
%1:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
17+
%1.sub_32bit:gr64_with_sub_8bit = AND32rr %1.sub_32bit:gr64_with_sub_8bit, %0.sub_32bit:gr64_with_sub_8bit, implicit-def dead $eflags, implicit-def %1:gr64_with_sub_8bit
18+
%0:gr64_with_sub_8bit = COPY %1:gr64_with_sub_8bit
19+
RET 0, implicit %0
20+
...
21+
# In case the MIR for some reason contains more than one implicit-def of the destination reg, then all should be updated.
22+
---
23+
name: two_implicit_defs_dst
24+
tracksRegLiveness: true
25+
body: |
26+
bb.0:
27+
; CHECK-LABEL: name: two_implicit_defs_dst
28+
; CHECK: [[MOV64rm:%[0-9]+]]:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
29+
; CHECK-NEXT: [[MOV64rm1:%[0-9]+]]:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
30+
; CHECK-NEXT: [[MOV64rm:%[0-9]+]].sub_32bit:gr64_with_sub_8bit = AND32rr [[MOV64rm]].sub_32bit, [[MOV64rm1]].sub_32bit, implicit-def dead $eflags, implicit-def [[MOV64rm]], implicit-def [[MOV64rm]]
31+
; CHECK-NEXT: RET 0, implicit [[MOV64rm]]
32+
%0:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
33+
%1:gr64_with_sub_8bit = MOV64rm $noreg, 1, $noreg, 0, $noreg :: (load (s64) from `ptr null`)
34+
%1.sub_32bit:gr64_with_sub_8bit = AND32rr %1.sub_32bit:gr64_with_sub_8bit, %0.sub_32bit:gr64_with_sub_8bit, implicit-def dead $eflags, implicit-def %1:gr64_with_sub_8bit, implicit-def %1:gr64_with_sub_8bit
35+
%0:gr64_with_sub_8bit = COPY %1:gr64_with_sub_8bit
36+
RET 0, implicit %0
37+
...

0 commit comments

Comments
 (0)