Skip to content

Commit 1e9a296

Browse files
authored
[Xtensa] Implement branch analysis. (#110959)
1 parent d897ea3 commit 1e9a296

File tree

7 files changed

+1237
-60
lines changed

7 files changed

+1237
-60
lines changed

llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,298 @@ void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
185185
report_fatal_error("Unsupported load immediate value");
186186
}
187187
}
188+
189+
bool XtensaInstrInfo::reverseBranchCondition(
190+
SmallVectorImpl<MachineOperand> &Cond) const {
191+
assert(Cond.size() <= 4 && "Invalid branch condition!");
192+
193+
switch (Cond[0].getImm()) {
194+
case Xtensa::BEQ:
195+
Cond[0].setImm(Xtensa::BNE);
196+
return false;
197+
case Xtensa::BNE:
198+
Cond[0].setImm(Xtensa::BEQ);
199+
return false;
200+
case Xtensa::BLT:
201+
Cond[0].setImm(Xtensa::BGE);
202+
return false;
203+
case Xtensa::BGE:
204+
Cond[0].setImm(Xtensa::BLT);
205+
return false;
206+
case Xtensa::BLTU:
207+
Cond[0].setImm(Xtensa::BGEU);
208+
return false;
209+
case Xtensa::BGEU:
210+
Cond[0].setImm(Xtensa::BLTU);
211+
return false;
212+
case Xtensa::BEQI:
213+
Cond[0].setImm(Xtensa::BNEI);
214+
return false;
215+
case Xtensa::BNEI:
216+
Cond[0].setImm(Xtensa::BEQI);
217+
return false;
218+
case Xtensa::BGEI:
219+
Cond[0].setImm(Xtensa::BLTI);
220+
return false;
221+
case Xtensa::BLTI:
222+
Cond[0].setImm(Xtensa::BGEI);
223+
return false;
224+
case Xtensa::BGEUI:
225+
Cond[0].setImm(Xtensa::BLTUI);
226+
return false;
227+
case Xtensa::BLTUI:
228+
Cond[0].setImm(Xtensa::BGEUI);
229+
return false;
230+
case Xtensa::BEQZ:
231+
Cond[0].setImm(Xtensa::BNEZ);
232+
return false;
233+
case Xtensa::BNEZ:
234+
Cond[0].setImm(Xtensa::BEQZ);
235+
return false;
236+
case Xtensa::BLTZ:
237+
Cond[0].setImm(Xtensa::BGEZ);
238+
return false;
239+
case Xtensa::BGEZ:
240+
Cond[0].setImm(Xtensa::BLTZ);
241+
return false;
242+
default:
243+
report_fatal_error("Invalid branch condition!");
244+
}
245+
}
246+
247+
bool XtensaInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
248+
MachineBasicBlock *&TBB,
249+
MachineBasicBlock *&FBB,
250+
SmallVectorImpl<MachineOperand> &Cond,
251+
bool AllowModify = false) const {
252+
// Most of the code and comments here are boilerplate.
253+
254+
// Start from the bottom of the block and work up, examining the
255+
// terminator instructions.
256+
MachineBasicBlock::iterator I = MBB.end();
257+
while (I != MBB.begin()) {
258+
--I;
259+
if (I->isDebugValue())
260+
continue;
261+
262+
// Working from the bottom, when we see a non-terminator instruction, we're
263+
// done.
264+
if (!isUnpredicatedTerminator(*I))
265+
break;
266+
267+
// A terminator that isn't a branch can't easily be handled by this
268+
// analysis.
269+
SmallVector<MachineOperand, 4> ThisCond;
270+
ThisCond.push_back(MachineOperand::CreateImm(0));
271+
const MachineOperand *ThisTarget;
272+
if (!isBranch(I, ThisCond, ThisTarget))
273+
return true;
274+
275+
// Can't handle indirect branches.
276+
if (!ThisTarget->isMBB())
277+
return true;
278+
279+
if (ThisCond[0].getImm() == Xtensa::J) {
280+
// Handle unconditional branches.
281+
if (!AllowModify) {
282+
TBB = ThisTarget->getMBB();
283+
continue;
284+
}
285+
286+
// If the block has any instructions after a JMP, delete them.
287+
while (std::next(I) != MBB.end())
288+
std::next(I)->eraseFromParent();
289+
290+
Cond.clear();
291+
FBB = 0;
292+
293+
// TBB is used to indicate the unconditinal destination.
294+
TBB = ThisTarget->getMBB();
295+
continue;
296+
}
297+
298+
// Working from the bottom, handle the first conditional branch.
299+
if (Cond.empty()) {
300+
// FIXME: add X86-style branch swap
301+
FBB = TBB;
302+
TBB = ThisTarget->getMBB();
303+
Cond.push_back(MachineOperand::CreateImm(ThisCond[0].getImm()));
304+
305+
// push remaining operands
306+
for (unsigned int i = 0; i < (I->getNumExplicitOperands() - 1); i++)
307+
Cond.push_back(I->getOperand(i));
308+
309+
continue;
310+
}
311+
312+
// Handle subsequent conditional branches.
313+
assert(Cond.size() <= 4);
314+
assert(TBB);
315+
316+
// Only handle the case where all conditional branches branch to the same
317+
// destination.
318+
if (TBB != ThisTarget->getMBB())
319+
return true;
320+
321+
// If the conditions are the same, we can leave them alone.
322+
unsigned OldCond = Cond[0].getImm();
323+
if (OldCond == ThisCond[0].getImm())
324+
continue;
325+
}
326+
327+
return false;
328+
}
329+
330+
unsigned XtensaInstrInfo::removeBranch(MachineBasicBlock &MBB,
331+
int *BytesRemoved) const {
332+
// Most of the code and comments here are boilerplate.
333+
MachineBasicBlock::iterator I = MBB.end();
334+
unsigned Count = 0;
335+
if (BytesRemoved)
336+
*BytesRemoved = 0;
337+
338+
while (I != MBB.begin()) {
339+
--I;
340+
SmallVector<MachineOperand, 4> Cond;
341+
Cond.push_back(MachineOperand::CreateImm(0));
342+
const MachineOperand *Target;
343+
if (!isBranch(I, Cond, Target))
344+
break;
345+
if (!Target->isMBB())
346+
break;
347+
// Remove the branch.
348+
if (BytesRemoved)
349+
*BytesRemoved += getInstSizeInBytes(*I);
350+
I->eraseFromParent();
351+
I = MBB.end();
352+
++Count;
353+
}
354+
return Count;
355+
}
356+
357+
unsigned XtensaInstrInfo::insertBranch(
358+
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
359+
ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
360+
unsigned Count = 0;
361+
if (BytesAdded)
362+
*BytesAdded = 0;
363+
if (FBB) {
364+
// Need to build two branches then
365+
// one to branch to TBB on Cond
366+
// and a second one immediately after to unconditionally jump to FBB
367+
Count = insertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded);
368+
auto &MI = *BuildMI(&MBB, DL, get(Xtensa::J)).addMBB(FBB);
369+
Count++;
370+
if (BytesAdded)
371+
*BytesAdded += getInstSizeInBytes(MI);
372+
return Count;
373+
}
374+
// This function inserts the branch at the end of the MBB
375+
Count += insertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded);
376+
return Count;
377+
}
378+
379+
unsigned XtensaInstrInfo::insertBranchAtInst(MachineBasicBlock &MBB,
380+
MachineBasicBlock::iterator I,
381+
MachineBasicBlock *TBB,
382+
ArrayRef<MachineOperand> Cond,
383+
const DebugLoc &DL,
384+
int *BytesAdded) const {
385+
// Shouldn't be a fall through.
386+
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
387+
assert(Cond.size() <= 4 &&
388+
"Xtensa branch conditions have less than four components!");
389+
390+
if (Cond.empty() || (Cond[0].getImm() == Xtensa::J)) {
391+
// Unconditional branch
392+
MachineInstr *MI = BuildMI(MBB, I, DL, get(Xtensa::J)).addMBB(TBB);
393+
if (BytesAdded && MI)
394+
*BytesAdded += getInstSizeInBytes(*MI);
395+
return 1;
396+
}
397+
398+
unsigned Count = 0;
399+
unsigned BR_C = Cond[0].getImm();
400+
MachineInstr *MI = nullptr;
401+
switch (BR_C) {
402+
case Xtensa::BEQ:
403+
case Xtensa::BNE:
404+
case Xtensa::BLT:
405+
case Xtensa::BLTU:
406+
case Xtensa::BGE:
407+
case Xtensa::BGEU:
408+
MI = BuildMI(MBB, I, DL, get(BR_C))
409+
.addReg(Cond[1].getReg())
410+
.addReg(Cond[2].getReg())
411+
.addMBB(TBB);
412+
break;
413+
case Xtensa::BEQI:
414+
case Xtensa::BNEI:
415+
case Xtensa::BLTI:
416+
case Xtensa::BLTUI:
417+
case Xtensa::BGEI:
418+
case Xtensa::BGEUI:
419+
MI = BuildMI(MBB, I, DL, get(BR_C))
420+
.addReg(Cond[1].getReg())
421+
.addImm(Cond[2].getImm())
422+
.addMBB(TBB);
423+
break;
424+
case Xtensa::BEQZ:
425+
case Xtensa::BNEZ:
426+
case Xtensa::BLTZ:
427+
case Xtensa::BGEZ:
428+
MI = BuildMI(MBB, I, DL, get(BR_C)).addReg(Cond[1].getReg()).addMBB(TBB);
429+
break;
430+
default:
431+
report_fatal_error("Invalid branch type!");
432+
}
433+
if (BytesAdded && MI)
434+
*BytesAdded += getInstSizeInBytes(*MI);
435+
++Count;
436+
return Count;
437+
}
438+
439+
bool XtensaInstrInfo::isBranch(const MachineBasicBlock::iterator &MI,
440+
SmallVectorImpl<MachineOperand> &Cond,
441+
const MachineOperand *&Target) const {
442+
unsigned OpCode = MI->getOpcode();
443+
switch (OpCode) {
444+
case Xtensa::J:
445+
case Xtensa::JX:
446+
case Xtensa::BR_JT:
447+
Cond[0].setImm(OpCode);
448+
Target = &MI->getOperand(0);
449+
return true;
450+
case Xtensa::BEQ:
451+
case Xtensa::BNE:
452+
case Xtensa::BLT:
453+
case Xtensa::BLTU:
454+
case Xtensa::BGE:
455+
case Xtensa::BGEU:
456+
Cond[0].setImm(OpCode);
457+
Target = &MI->getOperand(2);
458+
return true;
459+
460+
case Xtensa::BEQI:
461+
case Xtensa::BNEI:
462+
case Xtensa::BLTI:
463+
case Xtensa::BLTUI:
464+
case Xtensa::BGEI:
465+
case Xtensa::BGEUI:
466+
Cond[0].setImm(OpCode);
467+
Target = &MI->getOperand(2);
468+
return true;
469+
470+
case Xtensa::BEQZ:
471+
case Xtensa::BNEZ:
472+
case Xtensa::BLTZ:
473+
case Xtensa::BGEZ:
474+
Cond[0].setImm(OpCode);
475+
Target = &MI->getOperand(1);
476+
return true;
477+
478+
default:
479+
assert(!MI->getDesc().isBranch() && "Unknown branch opcode");
480+
return false;
481+
}
482+
}

llvm/lib/Target/Xtensa/XtensaInstrInfo.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,37 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
7474
void loadImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
7575
unsigned *Reg, int64_t Value) const;
7676

77+
bool
78+
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
79+
80+
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
81+
MachineBasicBlock *&FBB,
82+
SmallVectorImpl<MachineOperand> &Cond,
83+
bool AllowModify) const override;
84+
85+
unsigned removeBranch(MachineBasicBlock &MBB,
86+
int *BytesRemoved = nullptr) const override;
87+
88+
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
89+
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
90+
const DebugLoc &DL,
91+
int *BytesAdded = nullptr) const override;
92+
93+
unsigned insertBranchAtInst(MachineBasicBlock &MBB,
94+
MachineBasicBlock::iterator I,
95+
MachineBasicBlock *TBB,
96+
ArrayRef<MachineOperand> Cond, const DebugLoc &DL,
97+
int *BytesAdded) const;
98+
99+
// Return true if MI is a conditional or unconditional branch.
100+
// When returning true, set Cond to the mask of condition-code
101+
// values on which the instruction will branch, and set Target
102+
// to the operand that contains the branch target. This target
103+
// can be a register or a basic block.
104+
bool isBranch(const MachineBasicBlock::iterator &MI,
105+
SmallVectorImpl<MachineOperand> &Cond,
106+
const MachineOperand *&Target) const;
107+
77108
const XtensaSubtarget &getSubtarget() const { return STI; }
78109
};
79110
} // end namespace llvm

llvm/lib/Target/Xtensa/XtensaInstrInfo.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ def BBSI : RRI8_Inst<0x07, (outs),
417417
let imm8 = target;
418418
}
419419

420+
def : Pat<(brcond AR:$s, bb:$target), (BNEZ AR:$s, bb:$target)>;
421+
420422
//===----------------------------------------------------------------------===//
421423
// Call and jump instructions
422424
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)