Skip to content

Commit cdd6185

Browse files
committed
[Z80] Sink fixed stack call argument loads before RA
1 parent 8556b08 commit cdd6185

1 file changed

Lines changed: 189 additions & 0 deletions

File tree

llvm/lib/Target/Z80/Z80MachinePreRAOptimization.cpp

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
#include "MCTargetDesc/Z80MCTargetDesc.h"
1515
#include "Z80.h"
1616
#include "Z80InstrInfo.h"
17+
#include "llvm/ADT/SmallPtrSet.h"
1718
#include "llvm/CodeGen/LiveRegUnits.h"
1819
#include "llvm/CodeGen/MachineDominators.h"
20+
#include "llvm/CodeGen/MachineFrameInfo.h"
1921
#include "llvm/CodeGen/TargetInstrInfo.h"
2022
#include "llvm/CodeGen/TargetRegisterInfo.h"
2123
#include "llvm/CodeGen/TargetSubtargetInfo.h"
@@ -177,9 +179,189 @@ static bool isRegClassCompatibleForReplace(const TargetRegisterClass *DstRC,
177179
return DstRC->hasSubClassEq(RepRC);
178180
}
179181

182+
static bool isPhysicalCopyDef(const MachineInstr &MI) {
183+
if (MI.getOpcode() != TargetOpcode::COPY)
184+
return false;
185+
return MI.getOperand(0).getReg().isPhysical();
186+
}
187+
188+
static bool isCallSetupGlue(const MachineInstr &MI) {
189+
switch (MI.getOpcode()) {
190+
default:
191+
return false;
192+
case TargetOpcode::IMPLICIT_DEF:
193+
case TargetOpcode::INSERT_SUBREG:
194+
return true;
195+
case TargetOpcode::COPY:
196+
return MI.getOperand(0).getReg().isVirtual() &&
197+
MI.getOperand(1).getReg().isVirtual();
198+
}
199+
}
200+
201+
static bool callUsesReg(const MachineInstr &CallMI, Register Reg,
202+
const TargetRegisterInfo &TRI) {
203+
for (const MachineOperand &MO : CallMI.operands())
204+
if (MO.isReg() && MO.isUse() && MO.getReg() != Register() &&
205+
TRI.regsOverlap(MO.getReg(), Reg))
206+
return true;
207+
208+
return false;
209+
}
210+
211+
static bool reachesCallSetupUse(MachineInstr &MI, Register PhysReg,
212+
const TargetRegisterInfo &TRI) {
213+
MachineBasicBlock &MBB = *MI.getParent();
214+
auto E = MBB.end();
215+
for (auto I = std::next(MI.getIterator()); I != E; ++I) {
216+
if (I->isDebugInstr())
217+
continue;
218+
219+
if (I->isCall())
220+
return PhysReg == Register() || callUsesReg(*I, PhysReg, TRI);
221+
222+
if (PhysReg != Register() && I->modifiesRegister(PhysReg, &TRI))
223+
return false;
224+
225+
if (I->getOpcode() == Z80::PUSH16r || I->getOpcode() == Z80::PUSH24r ||
226+
isPhysicalCopyDef(*I) ||
227+
isCallSetupGlue(*I))
228+
continue;
229+
230+
return false;
231+
}
232+
233+
return false;
234+
}
235+
236+
static bool isAtOrBefore(MachineInstr &MI, MachineInstr &UseMI) {
237+
if (MI.getParent() != UseMI.getParent())
238+
return false;
239+
240+
for (auto I = MachineBasicBlock::iterator(MI), E = MI.getParent()->end();
241+
I != E; ++I)
242+
if (&*I == &UseMI)
243+
return true;
244+
245+
return false;
246+
}
247+
248+
static bool canMoveDefBeforeUse(Register Reg, MachineInstr &UserMI,
249+
MachineInstr &InsertMI,
250+
MachineRegisterInfo &MRI) {
251+
if (MRI.hasOneNonDBGUse(Reg))
252+
return true;
253+
254+
for (MachineOperand &MO : MRI.use_nodbg_operands(Reg)) {
255+
MachineInstr *OtherMI = MO.getParent();
256+
if (OtherMI == &UserMI)
257+
continue;
258+
if (OtherMI->getParent() != InsertMI.getParent())
259+
return false;
260+
if (isAtOrBefore(*OtherMI, InsertMI))
261+
return false;
262+
}
263+
264+
return true;
265+
}
266+
267+
static bool isImmutableFixedStackLoad(const MachineInstr &MI,
268+
const MachineFrameInfo &MFI,
269+
const TargetInstrInfo &TII) {
270+
int FI = 0;
271+
return TII.isLoadFromStackSlot(MI, FI) != Register() &&
272+
MFI.isFixedObjectIndex(FI) && MFI.isImmutableObjectIndex(FI) &&
273+
!MFI.isAliasedObjectIndex(FI);
274+
}
275+
276+
static bool collectFixedStackArgDefChain(
277+
Register Reg, MachineInstr &UserMI, MachineInstr &InsertMI,
278+
MachineRegisterInfo &MRI, const MachineFrameInfo &MFI,
279+
const TargetInstrInfo &TII,
280+
SmallVectorImpl<MachineInstr *> &Defs,
281+
SmallPtrSetImpl<MachineInstr *> &Seen, bool &HasFixedStackLoad) {
282+
if (!Reg.isVirtual())
283+
return false;
284+
285+
MachineInstr *DefMI = MRI.getUniqueVRegDef(Reg);
286+
if (!DefMI || !isAtOrBefore(*DefMI, UserMI) ||
287+
!canMoveDefBeforeUse(Reg, UserMI, InsertMI, MRI))
288+
return false;
289+
290+
if (!Seen.insert(DefMI).second)
291+
return true;
292+
293+
switch (DefMI->getOpcode()) {
294+
case TargetOpcode::COPY:
295+
if (!collectFixedStackArgDefChain(DefMI->getOperand(1).getReg(), *DefMI,
296+
InsertMI, MRI, MFI, TII, Defs, Seen,
297+
HasFixedStackLoad))
298+
return false;
299+
break;
300+
case TargetOpcode::IMPLICIT_DEF:
301+
break;
302+
case TargetOpcode::INSERT_SUBREG:
303+
if (!collectFixedStackArgDefChain(DefMI->getOperand(1).getReg(), *DefMI,
304+
InsertMI, MRI, MFI, TII, Defs, Seen,
305+
HasFixedStackLoad) ||
306+
!collectFixedStackArgDefChain(DefMI->getOperand(2).getReg(), *DefMI,
307+
InsertMI, MRI, MFI, TII, Defs, Seen,
308+
HasFixedStackLoad))
309+
return false;
310+
break;
311+
default:
312+
if (!isImmutableFixedStackLoad(*DefMI, MFI, TII))
313+
return false;
314+
315+
HasFixedStackLoad = true;
316+
break;
317+
}
318+
319+
Defs.push_back(DefMI);
320+
return true;
321+
}
322+
323+
static bool sinkFixedStackCallArgDefChain(MachineInstr &MI,
324+
MachineRegisterInfo &MRI,
325+
const MachineFrameInfo &MFI,
326+
const TargetInstrInfo &TII,
327+
const TargetRegisterInfo &TRI) {
328+
Register UseReg = Register();
329+
Register PhysReg = Register();
330+
331+
if (MI.getOpcode() == Z80::PUSH16r || MI.getOpcode() == Z80::PUSH24r) {
332+
UseReg = MI.getOperand(0).getReg();
333+
if (!reachesCallSetupUse(MI, Register(), TRI))
334+
return false;
335+
} else if (isPhysicalCopyDef(MI)) {
336+
PhysReg = MI.getOperand(0).getReg();
337+
UseReg = MI.getOperand(1).getReg();
338+
if (!reachesCallSetupUse(MI, PhysReg, TRI))
339+
return false;
340+
} else {
341+
return false;
342+
}
343+
344+
SmallVector<MachineInstr *, 4> Defs;
345+
SmallPtrSet<MachineInstr *, 4> Seen;
346+
bool HasFixedStackLoad = false;
347+
if (!collectFixedStackArgDefChain(UseReg, MI, MI, MRI, MFI, TII, Defs, Seen,
348+
HasFixedStackLoad) ||
349+
!HasFixedStackLoad)
350+
return false;
351+
352+
MachineBasicBlock &MBB = *MI.getParent();
353+
for (MachineInstr *DefMI : Defs)
354+
MBB.splice(MachineBasicBlock::iterator(MI), &MBB,
355+
MachineBasicBlock::iterator(*DefMI));
356+
357+
return true;
358+
}
359+
180360
bool Z80MachinePreRAOptimization::runOnMachineFunction(MachineFunction &MF) {
181361
bool Changed = false;
182362
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
363+
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
364+
const MachineFrameInfo &MFI = MF.getFrameInfo();
183365
MachineRegisterInfo &MRI = MF.getRegInfo();
184366
SmallSet<Register, 16> FoldAsLoadDefCandidates;
185367

@@ -221,6 +403,13 @@ bool Z80MachinePreRAOptimization::runOnMachineFunction(MachineFunction &MF) {
221403
}
222404
}
223405

406+
for (MachineBasicBlock &MBB : MF) {
407+
for (auto MII = MBB.begin(), MIE = MBB.end(); MII != MIE;) {
408+
MachineInstr *MI = &*MII++;
409+
Changed |= sinkFixedStackCallArgDefChain(*MI, MRI, MFI, TII, TRI);
410+
}
411+
}
412+
224413
for (MachineBasicBlock &MBB : MF) {
225414
for (auto MII = MBB.begin(), MIE = MBB.end(); MII != MIE;) {
226415
MachineInstr *MI = &*MII;

0 commit comments

Comments
 (0)