Skip to content

Commit 9acb41b

Browse files
JonPsson1tstellar
authored andcommitted
[SystemZ] Handle address clobbering in splitMove(). (#92105)
When expanding an L128 (which is used to reload i128) it is possible that the quadword destination register clobbers an address register. This patch adds an assertion against the case where both of the expanded parts clobber the address, and in the case where one of the expanded parts do so puts it last. Fixes #91437 (cherry picked from commit d6ee7e8)
1 parent 1665723 commit 9acb41b

File tree

2 files changed

+65
-26
lines changed

2 files changed

+65
-26
lines changed

llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp

+39-26
Original file line numberDiff line numberDiff line change
@@ -70,49 +70,62 @@ void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI,
7070
MachineBasicBlock *MBB = MI->getParent();
7171
MachineFunction &MF = *MBB->getParent();
7272

73-
// Get two load or store instructions. Use the original instruction for one
74-
// of them (arbitrarily the second here) and create a clone for the other.
75-
MachineInstr *EarlierMI = MF.CloneMachineInstr(&*MI);
76-
MBB->insert(MI, EarlierMI);
73+
// Get two load or store instructions. Use the original instruction for
74+
// one of them and create a clone for the other.
75+
MachineInstr *HighPartMI = MF.CloneMachineInstr(&*MI);
76+
MachineInstr *LowPartMI = &*MI;
77+
MBB->insert(LowPartMI, HighPartMI);
7778

7879
// Set up the two 64-bit registers and remember super reg and its flags.
79-
MachineOperand &HighRegOp = EarlierMI->getOperand(0);
80-
MachineOperand &LowRegOp = MI->getOperand(0);
80+
MachineOperand &HighRegOp = HighPartMI->getOperand(0);
81+
MachineOperand &LowRegOp = LowPartMI->getOperand(0);
8182
Register Reg128 = LowRegOp.getReg();
8283
unsigned Reg128Killed = getKillRegState(LowRegOp.isKill());
8384
unsigned Reg128Undef = getUndefRegState(LowRegOp.isUndef());
8485
HighRegOp.setReg(RI.getSubReg(HighRegOp.getReg(), SystemZ::subreg_h64));
8586
LowRegOp.setReg(RI.getSubReg(LowRegOp.getReg(), SystemZ::subreg_l64));
8687

87-
if (MI->mayStore()) {
88-
// Add implicit uses of the super register in case one of the subregs is
89-
// undefined. We could track liveness and skip storing an undefined
90-
// subreg, but this is hopefully rare (discovered with llvm-stress).
91-
// If Reg128 was killed, set kill flag on MI.
92-
unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit);
93-
MachineInstrBuilder(MF, EarlierMI).addReg(Reg128, Reg128UndefImpl);
94-
MachineInstrBuilder(MF, MI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed));
95-
}
96-
9788
// The address in the first (high) instruction is already correct.
9889
// Adjust the offset in the second (low) instruction.
99-
MachineOperand &HighOffsetOp = EarlierMI->getOperand(2);
100-
MachineOperand &LowOffsetOp = MI->getOperand(2);
90+
MachineOperand &HighOffsetOp = HighPartMI->getOperand(2);
91+
MachineOperand &LowOffsetOp = LowPartMI->getOperand(2);
10192
LowOffsetOp.setImm(LowOffsetOp.getImm() + 8);
10293

103-
// Clear the kill flags on the registers in the first instruction.
104-
if (EarlierMI->getOperand(0).isReg() && EarlierMI->getOperand(0).isUse())
105-
EarlierMI->getOperand(0).setIsKill(false);
106-
EarlierMI->getOperand(1).setIsKill(false);
107-
EarlierMI->getOperand(3).setIsKill(false);
108-
10994
// Set the opcodes.
11095
unsigned HighOpcode = getOpcodeForOffset(NewOpcode, HighOffsetOp.getImm());
11196
unsigned LowOpcode = getOpcodeForOffset(NewOpcode, LowOffsetOp.getImm());
11297
assert(HighOpcode && LowOpcode && "Both offsets should be in range");
98+
HighPartMI->setDesc(get(HighOpcode));
99+
LowPartMI->setDesc(get(LowOpcode));
100+
101+
MachineInstr *FirstMI = HighPartMI;
102+
if (MI->mayStore()) {
103+
FirstMI->getOperand(0).setIsKill(false);
104+
// Add implicit uses of the super register in case one of the subregs is
105+
// undefined. We could track liveness and skip storing an undefined
106+
// subreg, but this is hopefully rare (discovered with llvm-stress).
107+
// If Reg128 was killed, set kill flag on MI.
108+
unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit);
109+
MachineInstrBuilder(MF, HighPartMI).addReg(Reg128, Reg128UndefImpl);
110+
MachineInstrBuilder(MF, LowPartMI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed));
111+
} else {
112+
// If HighPartMI clobbers any of the address registers, it needs to come
113+
// after LowPartMI.
114+
auto overlapsAddressReg = [&](Register Reg) -> bool {
115+
return RI.regsOverlap(Reg, MI->getOperand(1).getReg()) ||
116+
RI.regsOverlap(Reg, MI->getOperand(3).getReg());
117+
};
118+
if (overlapsAddressReg(HighRegOp.getReg())) {
119+
assert(!overlapsAddressReg(LowRegOp.getReg()) &&
120+
"Both loads clobber address!");
121+
MBB->splice(HighPartMI, MBB, LowPartMI);
122+
FirstMI = LowPartMI;
123+
}
124+
}
113125

114-
EarlierMI->setDesc(get(HighOpcode));
115-
MI->setDesc(get(LowOpcode));
126+
// Clear the kill flags on the address registers in the first instruction.
127+
FirstMI->getOperand(1).setIsKill(false);
128+
FirstMI->getOperand(3).setIsKill(false);
116129
}
117130

118131
// Split ADJDYNALLOC instruction MI.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# RUN: llc -mtriple=s390x-linux-gnu -run-pass=postrapseudos \
2+
# RUN: %s -o - -verify-machineinstrs | FileCheck %s
3+
#
4+
# Test that a L128 reload do not overwrite an address register prematurely
5+
# after being split into two LGs.
6+
7+
--- |
8+
target triple = "s390x-unknown-unknown"
9+
10+
define void @fun() {
11+
ret void
12+
}
13+
14+
...
15+
16+
# CHECK: name: fun
17+
18+
---
19+
name: 'fun'
20+
body: |
21+
bb.0:
22+
liveins: $r4d, $r15d
23+
$r4q = L128 $r15d, 14920, killed $r4d
24+
Return
25+
26+
...

0 commit comments

Comments
 (0)