Skip to content

Commit 9677659

Browse files
committed
[Xtensa] Fix Hardware Loop optimization
Closes #43
1 parent 06bc8b3 commit 9677659

File tree

2 files changed

+93
-41
lines changed

2 files changed

+93
-41
lines changed

llvm/lib/Target/Xtensa/XtensaHardwareLoops.cpp

Lines changed: 93 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,10 @@ bool XtensaHardwareLoops::processLoop(MachineLoop *L) {
194194
MachineInstr *LII = nullptr; // LOOPINIT instruction
195195
MachineInstr *LEI = nullptr; // LOOPEND instruction
196196
MachineBasicBlock *LEMBB = nullptr;
197-
MachineBasicBlock *PH = L->getLoopPreheader();
197+
MachineBasicBlock *LH = L->getHeader();
198198
MachineBasicBlock *LastMBB = L->getLoopLatch();
199+
std::vector<MachineInstr *> LoopInitInsts;
200+
std::map<MachineBasicBlock *, MachineInstr *> LoopInitMap;
199201

200202
// Try to find LOOPEND instruction in the loop latch
201203
for (auto MBI = L->block_begin(), MBIE = L->block_end(); MBI != MBIE; ++MBI) {
@@ -207,40 +209,56 @@ bool XtensaHardwareLoops::processLoop(MachineLoop *L) {
207209
LEI = LMI;
208210
LEMBB = *MBI;
209211
}
212+
// Collect LOOPINIT instructions inside the loop
213+
if (LMI->getOpcode() == Xtensa::LOOPINIT) {
214+
LoopInitInsts.push_back(LMI);
215+
MachineBasicBlock *SB = LMI->getParent();
216+
while (!SB->isSuccessor(LH)) {
217+
for (auto SBI : SB->successors()) {
218+
if (!L->contains(SBI))
219+
continue;
220+
SB = SBI;
221+
break;
222+
}
223+
if (!L->contains(SB))
224+
llvm_unreachable("Wrong hardware loop");
225+
}
226+
LoopInitMap[SB] = LMI;
227+
}
210228
}
211229
VisitedMBBs.insert(*MBI);
212230
}
213231

214232
if (LEI != nullptr) {
215-
MachineBasicBlock *LH = L->getHeader();
216233
MachineBasicBlock::iterator LHI = LH->getFirstNonPHI();
217-
218-
if (!PH) {
219-
llvm_unreachable("Hardware loop predecessor not found");
220-
return false;
221-
}
222-
223-
MachineBasicBlock *LIMBB = PH;
224-
225-
// Try to find LOOPINIT instruction in predecessors chain
226-
while ((LII == nullptr) && (LIMBB != nullptr) &&
227-
((L->getParentLoop() == nullptr) ||
228-
(L->getParentLoop()->contains(LIMBB)))) {
229-
for (instr_iterator I = LIMBB->instr_begin(), E = LIMBB->instr_end();
230-
I != E; ++I) {
231-
MachineInstr *MI = &*I;
232-
if (MI->getOpcode() == Xtensa::LOOPINIT) {
233-
LII = MI;
234-
break;
234+
MachineBasicBlock *LIMBB = nullptr;
235+
236+
// Collect LOOPINIT instructions in predecessors from outter loop
237+
for (auto PBI : LH->predecessors()) {
238+
if (L->contains(PBI))
239+
continue;
240+
LIMBB = PBI;
241+
LII = nullptr;
242+
// Try to find LOOPINIT instructions in predecessor
243+
while ((LII == nullptr) && (LIMBB != nullptr) &&
244+
((L->getParentLoop() == nullptr) ||
245+
(L->getParentLoop()->contains(LIMBB)))) {
246+
for (instr_iterator I = LIMBB->instr_begin(), E = LIMBB->instr_end();
247+
I != E; ++I) {
248+
MachineInstr *MI = &*I;
249+
if (MI->getOpcode() == Xtensa::LOOPINIT) {
250+
LII = MI;
251+
break;
252+
}
235253
}
254+
if (LII == nullptr)
255+
LIMBB = *LIMBB->pred_begin();
236256
}
237-
if (LII == nullptr)
238-
LIMBB = *LIMBB->pred_begin();
239-
}
240-
241-
if (LII == nullptr) {
242-
llvm_unreachable("Hardware loop init instruction not found");
243-
return false;
257+
if (LII == nullptr) {
258+
llvm_unreachable("Hardware loop init instruction not found");
259+
return false;
260+
}
261+
LoopInitMap[PBI] = LII;
244262
}
245263

246264
DebugLoc DL = LII->getDebugLoc();
@@ -250,22 +268,30 @@ bool XtensaHardwareLoops::processLoop(MachineLoop *L) {
250268
// sub a, a, 1
251269
// bnez a, LH
252270
if (!checkLoopSize(L) || containsInvalidInstruction(L) ||
253-
(LEMBB != LastMBB) || (!checkLoopEndDisplacement(*LH->getParent(), LH, LEMBB))) {
271+
(LEMBB != LastMBB) ||
272+
(!checkLoopEndDisplacement(*LH->getParent(), LH, LEMBB))) {
254273
const MCInstrDesc &PD = TII->get(TargetOpcode::PHI);
255274
MachineInstr *NewPN = LH->getParent()->CreateMachineInstr(PD, DL);
256275
LH->insert(LH->begin(), NewPN);
257276
Register PR = MRI->createVirtualRegister(&Xtensa::ARRegClass);
258277
NewPN->addOperand(MachineOperand::CreateReg(PR, true));
259278

260-
MachineOperand MO =
261-
MachineOperand::CreateReg(LII->getOperand(0).getReg(), false);
262-
NewPN->addOperand(MO);
263-
NewPN->addOperand(MachineOperand::CreateMBB(PH));
264-
265279
Register IndR = MRI->createVirtualRegister(&Xtensa::ARRegClass);
266-
MO = MachineOperand::CreateReg(IndR, false);
267-
NewPN->addOperand(MO);
268-
NewPN->addOperand(MachineOperand::CreateMBB(LastMBB));
280+
281+
for (auto PB : LH->predecessors()) {
282+
283+
if (LoopInitMap.find(PB) != LoopInitMap.end()) {
284+
MachineOperand MO = MachineOperand::CreateReg(
285+
LoopInitMap[PB]->getOperand(0).getReg(), false);
286+
NewPN->addOperand(MO);
287+
NewPN->addOperand(MachineOperand::CreateMBB(PB));
288+
LoopInitMap[PB]->getParent()->erase(LoopInitMap[PB]);
289+
} else {
290+
MachineOperand MO = MachineOperand::CreateReg(IndR, false);
291+
NewPN->addOperand(MO);
292+
NewPN->addOperand(MachineOperand::CreateMBB(PB));
293+
}
294+
}
269295

270296
MachineInstrBuilder MIB =
271297
BuildMI(*LEMBB, LEI, LEI->getDebugLoc(), TII->get(Xtensa::ADDI), IndR)
@@ -276,15 +302,42 @@ bool XtensaHardwareLoops::processLoop(MachineLoop *L) {
276302
.addReg(IndR)
277303
.addMBB(LEI->getOperand(0).getMBB());
278304
LEMBB->erase(LEI);
279-
PH->erase(LII);
280305
return false;
281306
}
282307

283-
//Place LOOPSTART instruction in loop header
308+
// If several LOOPINIT instructions are dicovered then create PHI
309+
// function
310+
if (LoopInitMap.size() > 1) {
311+
const MCInstrDesc &PD = TII->get(TargetOpcode::PHI);
312+
MachineInstr *NewPN = LH->getParent()->CreateMachineInstr(PD, DL);
313+
LH->insert(LH->begin(), NewPN);
314+
Register PR = MRI->createVirtualRegister(&Xtensa::ARRegClass);
315+
NewPN->addOperand(MachineOperand::CreateReg(PR, true));
316+
317+
for (auto PB : LH->predecessors()) {
318+
319+
if (LoopInitMap.find(PB) != LoopInitMap.end()) {
320+
MachineOperand MO = MachineOperand::CreateReg(
321+
LoopInitMap[PB]->getOperand(0).getReg(), false);
322+
NewPN->addOperand(MO);
323+
NewPN->addOperand(MachineOperand::CreateMBB(PB));
324+
LoopInitMap[PB]->getParent()->erase(LoopInitMap[PB]);
325+
} else {
326+
MachineOperand MO = MachineOperand::CreateReg(PR, false);
327+
NewPN->addOperand(MO);
328+
NewPN->addOperand(MachineOperand::CreateMBB(PB));
329+
}
330+
}
331+
LII = NewPN;
332+
}
333+
284334
BuildMI(*LH, LHI, DL, TII->get(Xtensa::LOOPSTART))
285335
.addReg(LII->getOperand(0).getReg())
286-
.addMBB(LastMBB);
287-
PH->erase(LII);
336+
.addMBB(LEMBB);
337+
338+
if (LII->getOpcode() == Xtensa::LOOPINIT)
339+
LII->getParent()->erase(LII);
340+
288341
return true;
289342
}
290343

llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,6 @@ bool XtensaInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
317317
return true;
318318
case Xtensa::LOOPEND:
319319
BrOffset += 4;
320-
BrOffset += 3 * 3; // 2*NOP + LOOP instrucions
321320
assert((BrOffset <= 0) && "Wrong hardware loop");
322321
return true;
323322
case Xtensa::BR_JT:

0 commit comments

Comments
 (0)