Skip to content

Commit 42c2ff8

Browse files
committed
Split out conditional instruction detection into new pass.
1 parent 14d1099 commit 42c2ff8

File tree

6 files changed

+209
-142
lines changed

6 files changed

+209
-142
lines changed

llvm/lib/Target/Z80/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ set(sources
3131
Z80ISelLowering.cpp
3232
Z80InstrInfo.cpp
3333
Z80MCInstLower.cpp
34+
Z80MachineEarlyOptimization.cpp
3435
Z80MachineLateOptimization.cpp
3536
Z80PostSelectCombiner.cpp
3637
Z80RegisterInfo.cpp

llvm/lib/Target/Z80/Z80.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ InstructionSelector *createZ80InstructionSelector(const Z80TargetMachine &TM,
3030
Z80Subtarget &,
3131
Z80RegisterBankInfo &);
3232
FunctionPass *createZ80PostSelectCombiner();
33+
FunctionPass *createZ80MachineEarlyOptimizationPass();
3334
FunctionPass *createZ80MachineLateOptimizationPass();
3435

3536
void initializeZ80PreLegalizerCombinerPass(PassRegistry &);
3637
void initializeZ80PostLegalizerCombinerPass(PassRegistry &);
3738
void initializeZ80PostSelectCombinerPass(PassRegistry &);
39+
void initializeZ80MachineEarlyOptimizationPass(PassRegistry &);
3840
void initializeZ80MachineLateOptimizationPass(PassRegistry &);
3941

4042
} // namespace llvm
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
//=== lib/Target/Z80/Z80MachineEarlyOptimization.cpp ----------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This pass does combining of machine instructions at the generic MI level,
10+
// before register allocation.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "MCTargetDesc/Z80MCTargetDesc.h"
15+
#include "Z80.h"
16+
#include "Z80InstrInfo.h"
17+
#include "llvm/CodeGen/LiveRegUnits.h"
18+
#include "llvm/CodeGen/MachineDominators.h"
19+
#include "llvm/CodeGen/TargetInstrInfo.h"
20+
#include "llvm/CodeGen/TargetRegisterInfo.h"
21+
#include "llvm/CodeGen/TargetSubtargetInfo.h"
22+
#include "llvm/IR/Constants.h"
23+
#include "llvm/Support/Debug.h"
24+
25+
#define DEBUG_TYPE "z80-machine-early-opt"
26+
27+
using namespace llvm;
28+
29+
namespace {
30+
cl::opt<unsigned> CondCallThreshold("z80-cond-call-threshold", cl::Hidden,
31+
cl::init(10));
32+
33+
class Z80MachineEarlyOptimization : public MachineFunctionPass {
34+
public:
35+
static char ID;
36+
37+
Z80MachineEarlyOptimization() : MachineFunctionPass(ID) {}
38+
39+
StringRef getPassName() const override {
40+
return "Z80 Machine Early Optimization";
41+
}
42+
43+
bool runOnMachineFunction(MachineFunction &MF) override;
44+
};
45+
} // end anonymous namespace
46+
47+
bool Z80MachineEarlyOptimization::runOnMachineFunction(MachineFunction &MF) {
48+
bool Changed = false;
49+
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
50+
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
51+
MachineRegisterInfo &MRI = MF.getRegInfo();
52+
53+
for (MachineBasicBlock &MBB : MF) {
54+
MachineBasicBlock *TrueMBB = nullptr, *FalseMBB = nullptr;
55+
SmallVector<MachineOperand, 1> Cond;
56+
if (TII.analyzeBranch(MBB, TrueMBB, FalseMBB, Cond, false) || Cond.empty())
57+
continue;
58+
if (!FalseMBB)
59+
FalseMBB = &*std::next(MBB.getIterator());
60+
assert(TrueMBB && FalseMBB && "Expected to be nonnull");
61+
for (int I = 0; I != 2; ++I) {
62+
if (TrueMBB->succ_empty() && TrueMBB->isReturnBlock()) {
63+
auto II = TrueMBB->begin();
64+
while (II->isCopy() || II->isMetaInstruction())
65+
++II;
66+
if (++II == TrueMBB->end()) {
67+
// Unimplemented until FPE works.
68+
//Changed = true;
69+
}
70+
}
71+
if (TII.reverseBranchCondition(Cond))
72+
break;
73+
std::swap(TrueMBB, FalseMBB);
74+
}
75+
// Separate loop because we want to prefer the above optimization.
76+
for (int I = 0; I != 2; ++I) {
77+
if (TrueMBB->pred_size() == 1 && TrueMBB->succ_size() == 1 &&
78+
TrueMBB->isSuccessor(FalseMBB)) {
79+
MachineBasicBlock::iterator I = TrueMBB->begin();
80+
MachineBasicBlock::iterator E = TrueMBB->getFirstTerminator();
81+
if (I != E && TII.isFrameSetup(*I) && TII.isFrameInstr(*--E) &&
82+
I != E) {
83+
unsigned Cost = 0;
84+
MachineInstr *CallMI = nullptr;
85+
struct Result {
86+
Register PhysReg, TrueReg, FalseReg, ResReg;
87+
};
88+
SmallVector<Result, 4> Results;
89+
while (++I != E) {
90+
++Cost;
91+
unsigned Opc = I->getOpcode();
92+
if (Opc == Z80::CALL16 || Opc == Z80::CALL24) {
93+
if (CallMI) {
94+
CallMI = nullptr;
95+
break;
96+
}
97+
CallMI = &*I;
98+
}
99+
if (TII.isFrameInstr(*I) ||
100+
(!CallMI && I->modifiesRegister(Z80::F, &TRI))) {
101+
CallMI = nullptr;
102+
break;
103+
}
104+
if (CallMI && Opc == TargetOpcode::COPY) {
105+
if (Results.size() == 4) {
106+
CallMI = nullptr;
107+
break;
108+
}
109+
Result &Res = Results.emplace_back();
110+
Res.TrueReg = I->getOperand(0).getReg();
111+
Res.PhysReg = I->getOperand(1).getReg();
112+
assert(Res.TrueReg.isVirtual() && Res.PhysReg.isPhysical() &&
113+
"Expected phys to virt reg copy inside call sequence");
114+
}
115+
}
116+
for (I = FalseMBB->begin(), E = FalseMBB->end(); CallMI && I != E && I->isPHI();
117+
++I) {
118+
if (I->getNumOperands() != 5) {
119+
CallMI = nullptr;
120+
break;
121+
}
122+
Register FalseReg, TrueReg;
123+
for (unsigned OpNo = 1; CallMI && OpNo != 5; OpNo += 2) {
124+
Register Reg = I->getOperand(OpNo).getReg();
125+
MachineBasicBlock &PredMBB = *I->getOperand(OpNo + 1).getMBB();
126+
if (&PredMBB == &MBB)
127+
FalseReg = Reg;
128+
else if (&PredMBB == TrueMBB)
129+
TrueReg = Reg;
130+
else
131+
CallMI = nullptr;
132+
}
133+
bool Found = false;
134+
for (Result &Res : Results) {
135+
if (Res.TrueReg != TrueReg)
136+
continue;
137+
if (Res.FalseReg.isValid())
138+
break;
139+
Res.FalseReg = FalseReg;
140+
Res.ResReg = I->getOperand(0).getReg();
141+
Found = true;
142+
break;
143+
}
144+
if (!Found)
145+
CallMI = nullptr;
146+
}
147+
if (CallMI) {
148+
for (Result &Res : Results) {
149+
if (!Res.FalseReg.isValid() ||
150+
CallMI->readsRegister(Res.PhysReg)) {
151+
CallMI = nullptr;
152+
break;
153+
}
154+
}
155+
}
156+
if (CallMI && Cost < CondCallThreshold) {
157+
Register TempReg = MRI.createVirtualRegister(&Z80::F8RegClass);
158+
DebugLoc DL = MBB.findBranchDebugLoc();
159+
MBB.removeSuccessor(FalseMBB);
160+
TII.removeBranch(MBB);
161+
BuildMI(&MBB, DL, TII.get(TargetOpcode::COPY), TempReg)
162+
.addReg(Z80::F);
163+
if (!MBB.isLayoutSuccessor(TrueMBB))
164+
TII.insertUnconditionalBranch(MBB, TrueMBB, DL);
165+
BuildMI(*TrueMBB, TrueMBB->begin(), DL, TII.get(TargetOpcode::COPY),
166+
Z80::F).addReg(TempReg);
167+
CallMI->setDesc(TII.get(CallMI->getOpcode() == Z80::CALL24
168+
? Z80::CALL24CC : Z80::CALL16CC));
169+
auto RegMask = CallMI->getOperand(1).getRegMask();
170+
CallMI->RemoveOperand(1);
171+
MachineInstrBuilder(MF, CallMI)
172+
.add(Cond[0]).addRegMask(RegMask)
173+
.addReg(Z80::F, RegState::Implicit);
174+
for (Result &Res : Results) {
175+
BuildMI(*TrueMBB, CallMI, CallMI->getDebugLoc(),
176+
TII.get(TargetOpcode::COPY), Res.PhysReg)
177+
.addReg(Res.FalseReg);
178+
CallMI->addRegisterKilled(Res.PhysReg, &TRI, true);
179+
}
180+
Changed = true;
181+
}
182+
}
183+
}
184+
if (TII.reverseBranchCondition(Cond))
185+
break;
186+
std::swap(TrueMBB, FalseMBB);
187+
}
188+
}
189+
190+
return Changed;
191+
}
192+
193+
char Z80MachineEarlyOptimization::ID = 0;
194+
INITIALIZE_PASS(Z80MachineEarlyOptimization, DEBUG_TYPE,
195+
"Optimize Z80 machine instrs before regselect", false, false)
196+
197+
namespace llvm {
198+
FunctionPass *createZ80MachineEarlyOptimizationPass() {
199+
return new Z80MachineEarlyOptimization();
200+
}
201+
} // end namespace llvm

llvm/lib/Target/Z80/Z80MachineLateOptimization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//=== lib/CodeGen/GlobalISel/Z80MachineLateOptimization.cpp ---------------===//
1+
//=== lib/Target/Z80/Z80MachineLateOptimization.cpp -----------------------===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +7,7 @@
77
//===----------------------------------------------------------------------===//
88
//
99
// This pass does combining of machine instructions at the generic MI level,
10-
// before the legalizer.
10+
// after register allocation.
1111
//
1212
//===----------------------------------------------------------------------===//
1313

llvm/lib/Target/Z80/Z80PostSelectCombiner.cpp

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525

2626
using namespace llvm;
2727

28-
static cl::opt<unsigned> CondCallThreshold("z80-cond-call-threshold",
29-
cl::Hidden, cl::init(10));
30-
3128
namespace {
3229
class Z80PostSelectCombiner : public MachineFunctionPass {
3330
public:
@@ -280,143 +277,6 @@ bool Z80PostSelectCombiner::runOnMachineFunction(MachineFunction &MF) {
280277
}
281278
}
282279

283-
for (MachineBasicBlock &MBB : MF) {
284-
MachineBasicBlock *TrueMBB = nullptr, *FalseMBB = nullptr;
285-
SmallVector<MachineOperand, 1> Cond;
286-
if (TII.analyzeBranch(MBB, TrueMBB, FalseMBB, Cond, false) || Cond.empty())
287-
continue;
288-
if (!FalseMBB)
289-
FalseMBB = &*std::next(MBB.getIterator());
290-
assert(TrueMBB && FalseMBB && "Expected to be nonnull");
291-
for (int I = 0; I != 2; ++I) {
292-
if (TrueMBB->succ_empty() && TrueMBB->isReturnBlock()) {
293-
auto II = TrueMBB->begin();
294-
while (II->isCopy() || II->isMetaInstruction())
295-
++II;
296-
if (++II == TrueMBB->end()) {
297-
// Unimplemented until FPE works.
298-
//Changed = true;
299-
}
300-
}
301-
if (TII.reverseBranchCondition(Cond))
302-
break;
303-
std::swap(TrueMBB, FalseMBB);
304-
}
305-
// Separate loop because we want to prefer the above optimization.
306-
for (int I = 0; I != 2; ++I) {
307-
if (TrueMBB->pred_size() == 1 && TrueMBB->succ_size() == 1 &&
308-
TrueMBB->isSuccessor(FalseMBB)) {
309-
MachineBasicBlock::iterator I = TrueMBB->begin();
310-
MachineBasicBlock::iterator E = TrueMBB->getFirstTerminator();
311-
if (I != E && TII.isFrameSetup(*I) && TII.isFrameInstr(*--E) &&
312-
I != E) {
313-
unsigned Cost = 0;
314-
MachineInstr *CallMI = nullptr;
315-
struct Result {
316-
Register PhysReg, TrueReg, FalseReg, ResReg;
317-
};
318-
SmallVector<Result, 4> Results;
319-
while (++I != E) {
320-
++Cost;
321-
unsigned Opc = I->getOpcode();
322-
if (Opc == Z80::CALL16 || Opc == Z80::CALL24) {
323-
if (CallMI) {
324-
CallMI = nullptr;
325-
break;
326-
}
327-
CallMI = &*I;
328-
}
329-
if (TII.isFrameInstr(*I) ||
330-
(!CallMI && I->modifiesRegister(Z80::F, &TRI))) {
331-
CallMI = nullptr;
332-
break;
333-
}
334-
if (CallMI && Opc == TargetOpcode::COPY) {
335-
if (Results.size() == 4) {
336-
CallMI = nullptr;
337-
break;
338-
}
339-
Result &Res = Results.emplace_back();
340-
Res.TrueReg = I->getOperand(0).getReg();
341-
Res.PhysReg = I->getOperand(1).getReg();
342-
assert(Res.TrueReg.isVirtual() && Res.PhysReg.isPhysical() &&
343-
"Expected phys to virt reg copy inside call sequence");
344-
}
345-
}
346-
for (I = FalseMBB->begin(), E = FalseMBB->end(); CallMI && I != E && I->isPHI();
347-
++I) {
348-
if (I->getNumOperands() != 5) {
349-
CallMI = nullptr;
350-
break;
351-
}
352-
Register FalseReg, TrueReg;
353-
for (unsigned OpNo = 1; CallMI && OpNo != 5; OpNo += 2) {
354-
Register Reg = I->getOperand(OpNo).getReg();
355-
MachineBasicBlock &PredMBB = *I->getOperand(OpNo + 1).getMBB();
356-
if (&PredMBB == &MBB)
357-
FalseReg = Reg;
358-
else if (&PredMBB == TrueMBB)
359-
TrueReg = Reg;
360-
else
361-
CallMI = nullptr;
362-
}
363-
bool Found = false;
364-
for (Result &Res : Results) {
365-
if (Res.TrueReg != TrueReg)
366-
continue;
367-
if (Res.FalseReg.isValid())
368-
break;
369-
Res.FalseReg = FalseReg;
370-
Res.ResReg = I->getOperand(0).getReg();
371-
Found = true;
372-
break;
373-
}
374-
if (!Found)
375-
CallMI = nullptr;
376-
}
377-
if (CallMI) {
378-
for (Result &Res : Results) {
379-
if (!Res.FalseReg.isValid() ||
380-
CallMI->readsRegister(Res.PhysReg)) {
381-
CallMI = nullptr;
382-
break;
383-
}
384-
}
385-
}
386-
if (CallMI && Cost < CondCallThreshold) {
387-
Register TempReg = MRI.createVirtualRegister(&Z80::F8RegClass);
388-
DebugLoc DL = MBB.findBranchDebugLoc();
389-
MBB.removeSuccessor(FalseMBB);
390-
TII.removeBranch(MBB);
391-
BuildMI(&MBB, DL, TII.get(TargetOpcode::COPY), TempReg)
392-
.addReg(Z80::F);
393-
if (!MBB.isLayoutSuccessor(TrueMBB))
394-
TII.insertUnconditionalBranch(MBB, TrueMBB, DL);
395-
BuildMI(*TrueMBB, TrueMBB->begin(), DL, TII.get(TargetOpcode::COPY),
396-
Z80::F).addReg(TempReg);
397-
CallMI->setDesc(TII.get(CallMI->getOpcode() == Z80::CALL24
398-
? Z80::CALL24CC : Z80::CALL16CC));
399-
auto RegMask = CallMI->getOperand(1).getRegMask();
400-
CallMI->RemoveOperand(1);
401-
MachineInstrBuilder(MF, CallMI)
402-
.add(Cond[0]).addRegMask(RegMask)
403-
.addReg(Z80::F, RegState::Implicit);
404-
for (Result &Res : Results) {
405-
BuildMI(*TrueMBB, CallMI, CallMI->getDebugLoc(),
406-
TII.get(TargetOpcode::COPY), Res.PhysReg)
407-
.addReg(Res.FalseReg);
408-
CallMI->addRegisterKilled(Res.PhysReg, &TRI, true);
409-
}
410-
Changed = true;
411-
}
412-
}
413-
}
414-
if (TII.reverseBranchCondition(Cond))
415-
break;
416-
std::swap(TrueMBB, FalseMBB);
417-
}
418-
}
419-
420280
return Changed;
421281
}
422282

0 commit comments

Comments
 (0)