Skip to content

Commit 0460557

Browse files
committed
[Xtensa] Implement branch relaxation.
Implement insertIndirectBranch function and other functions needed by Branch Relaxation pass. Also implement estimateFunctionSizeInBytes function in MachineFunction class.
1 parent 9f79615 commit 0460557

12 files changed

+592
-10
lines changed

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,10 @@ class LLVM_ABI MachineFunction {
868868
/// it are renumbered.
869869
void RenumberBlocks(MachineBasicBlock *MBBFrom = nullptr);
870870

871+
/// Return an estimate of the function's code size,
872+
/// taking into account block and function alignment
873+
int64_t estimateFunctionSizeInBytes();
874+
871875
/// print - Print out the MachineFunction in a format suitable for debugging
872876
/// to the specified stream.
873877
void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;

llvm/lib/CodeGen/MachineFunction.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,37 @@ void MachineFunction::RenumberBlocks(MachineBasicBlock *MBB) {
378378
MBBNumberingEpoch++;
379379
}
380380

381+
int64_t MachineFunction::estimateFunctionSizeInBytes() {
382+
const TargetInstrInfo &TII = *getSubtarget().getInstrInfo();
383+
const Align FunctionAlignment = getAlignment();
384+
MachineFunction::iterator MBBI = begin(), E = end();
385+
/// Offset - Distance from the beginning of the function to the end
386+
/// of the basic block.
387+
int64_t Offset = 0;
388+
389+
for (; MBBI != E; ++MBBI) {
390+
const Align Alignment = MBBI->getAlignment();
391+
int64_t BlockSize = 0;
392+
393+
for (auto &MI : *MBBI) {
394+
BlockSize += TII.getInstSizeInBytes(MI);
395+
}
396+
397+
int64_t OffsetBB;
398+
if (Alignment <= FunctionAlignment) {
399+
OffsetBB = alignTo(Offset, Alignment);
400+
} else {
401+
// The alignment of this MBB is larger than the function's alignment, so
402+
// we can't tell whether or not it will insert nops. Assume that it will.
403+
OffsetBB = alignTo(Offset, Alignment) + Alignment.value() -
404+
FunctionAlignment.value();
405+
}
406+
Offset = OffsetBB + BlockSize;
407+
}
408+
409+
return Offset;
410+
}
411+
381412
/// This method iterates over the basic blocks and assigns their IsBeginSection
382413
/// and IsEndSection fields. This must be called after MBB layout is finalized
383414
/// and the SectionID's are assigned to MBBs.

llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
6969
const BlockAddress *BA =
7070
cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress();
7171
MCSym = GetBlockAddressSymbol(BA);
72+
} else if (ACPV->isMachineBasicBlock()) {
73+
const MachineBasicBlock *MBB = cast<XtensaConstantPoolMBB>(ACPV)->getMBB();
74+
MCSym = MBB->getSymbol();
7275
} else if (ACPV->isJumpTable()) {
7376
unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex();
7477
MCSym = this->GetJTISymbol(Idx, false);

llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "XtensaFrameLowering.h"
1414
#include "XtensaInstrInfo.h"
15+
#include "XtensaMachineFunctionInfo.h"
1516
#include "XtensaSubtarget.h"
1617
#include "llvm/CodeGen/MachineFrameInfo.h"
1718
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -260,14 +261,26 @@ void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
260261
// Set scavenging frame index if necessary.
261262
MachineFrameInfo &MFI = MF.getFrameInfo();
262263
uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
264+
auto *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
265+
unsigned ScavSlotsNum = 0;
263266

264-
if (isInt<12>(MaxSPOffset))
265-
return;
267+
if (!isInt<12>(MaxSPOffset))
268+
ScavSlotsNum = 1;
269+
270+
// Far branches over 18-bit offset require a spill slot for scratch register.
271+
bool IsLargeFunction = !isInt<18>(MF.estimateFunctionSizeInBytes());
272+
if (IsLargeFunction)
273+
ScavSlotsNum = std::max(ScavSlotsNum, 1u);
266274

267275
const TargetRegisterClass &RC = Xtensa::ARRegClass;
268276
unsigned Size = TRI->getSpillSize(RC);
269277
Align Alignment = TRI->getSpillAlign(RC);
270-
int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
278+
for (unsigned I = 0; I < ScavSlotsNum; I++) {
279+
int FI = MFI.CreateStackObject(Size, Alignment, false);
280+
RS->addScavengingFrameIndex(FI);
271281

272-
RS->addScavengingFrameIndex(FI);
282+
if (IsLargeFunction &&
283+
XtensaFI->getBranchRelaxationScratchFrameIndex() == -1)
284+
XtensaFI->setBranchRelaxationScratchFrameIndex(FI);
285+
}
273286
}

llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "XtensaInstrInfo.h"
16+
#include "XtensaConstantPoolValue.h"
17+
#include "XtensaMachineFunctionInfo.h"
1618
#include "XtensaTargetMachine.h"
1719
#include "llvm/CodeGen/MachineConstantPool.h"
1820
#include "llvm/CodeGen/MachineFrameInfo.h"
1921
#include "llvm/CodeGen/MachineInstrBuilder.h"
2022
#include "llvm/CodeGen/MachineRegisterInfo.h"
23+
#include "llvm/CodeGen/RegisterScavenging.h"
2124

2225
#define GET_INSTRINFO_CTOR_DTOR
2326
#include "XtensaGenInstrInfo.inc"
@@ -186,6 +189,18 @@ void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
186189
}
187190
}
188191

192+
unsigned XtensaInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
193+
switch (MI.getOpcode()) {
194+
case TargetOpcode::INLINEASM: { // Inline Asm: Variable size.
195+
const MachineFunction *MF = MI.getParent()->getParent();
196+
const char *AsmStr = MI.getOperand(0).getSymbolName();
197+
return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
198+
}
199+
default:
200+
return MI.getDesc().getSize();
201+
}
202+
}
203+
189204
bool XtensaInstrInfo::reverseBranchCondition(
190205
SmallVectorImpl<MachineOperand> &Cond) const {
191206
assert(Cond.size() <= 4 && "Invalid branch condition!");
@@ -244,6 +259,74 @@ bool XtensaInstrInfo::reverseBranchCondition(
244259
}
245260
}
246261

262+
MachineBasicBlock *
263+
XtensaInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
264+
unsigned OpCode = MI.getOpcode();
265+
switch (OpCode) {
266+
case Xtensa::BR_JT:
267+
case Xtensa::JX:
268+
return nullptr;
269+
case Xtensa::J:
270+
return MI.getOperand(0).getMBB();
271+
case Xtensa::BEQ:
272+
case Xtensa::BNE:
273+
case Xtensa::BLT:
274+
case Xtensa::BLTU:
275+
case Xtensa::BGE:
276+
case Xtensa::BGEU:
277+
return MI.getOperand(2).getMBB();
278+
case Xtensa::BEQI:
279+
case Xtensa::BNEI:
280+
case Xtensa::BLTI:
281+
case Xtensa::BLTUI:
282+
case Xtensa::BGEI:
283+
case Xtensa::BGEUI:
284+
return MI.getOperand(2).getMBB();
285+
case Xtensa::BEQZ:
286+
case Xtensa::BNEZ:
287+
case Xtensa::BLTZ:
288+
case Xtensa::BGEZ:
289+
return MI.getOperand(1).getMBB();
290+
default:
291+
llvm_unreachable("Unknown branch opcode");
292+
}
293+
}
294+
295+
bool XtensaInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
296+
int64_t BrOffset) const {
297+
switch (BranchOp) {
298+
case Xtensa::J:
299+
BrOffset -= 4;
300+
return isIntN(18, BrOffset);
301+
case Xtensa::JX:
302+
return true;
303+
case Xtensa::BR_JT:
304+
return true;
305+
case Xtensa::BEQ:
306+
case Xtensa::BNE:
307+
case Xtensa::BLT:
308+
case Xtensa::BLTU:
309+
case Xtensa::BGE:
310+
case Xtensa::BGEU:
311+
case Xtensa::BEQI:
312+
case Xtensa::BNEI:
313+
case Xtensa::BLTI:
314+
case Xtensa::BLTUI:
315+
case Xtensa::BGEI:
316+
case Xtensa::BGEUI:
317+
BrOffset -= 4;
318+
return isIntN(8, BrOffset);
319+
case Xtensa::BEQZ:
320+
case Xtensa::BNEZ:
321+
case Xtensa::BLTZ:
322+
case Xtensa::BGEZ:
323+
BrOffset -= 4;
324+
return isIntN(12, BrOffset);
325+
default:
326+
llvm_unreachable("Unknown branch opcode");
327+
}
328+
}
329+
247330
bool XtensaInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
248331
MachineBasicBlock *&TBB,
249332
MachineBasicBlock *&FBB,
@@ -376,6 +459,130 @@ unsigned XtensaInstrInfo::insertBranch(
376459
return Count;
377460
}
378461

462+
void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
463+
MachineBasicBlock &DestBB,
464+
MachineBasicBlock &RestoreBB,
465+
const DebugLoc &DL, int64_t BrOffset,
466+
RegScavenger *RS) const {
467+
assert(RS && "RegScavenger required for long branching");
468+
assert(MBB.empty() &&
469+
"new block should be inserted for expanding unconditional branch");
470+
assert(MBB.pred_size() == 1);
471+
472+
MachineFunction *MF = MBB.getParent();
473+
MachineRegisterInfo &MRI = MF->getRegInfo();
474+
MachineConstantPool *ConstantPool = MF->getConstantPool();
475+
auto *XtensaFI = MF->getInfo<XtensaMachineFunctionInfo>();
476+
MachineBasicBlock *JumpToMBB = &DestBB;
477+
478+
if (!isInt<32>(BrOffset))
479+
report_fatal_error(
480+
"Branch offsets outside of the signed 32-bit range not supported");
481+
482+
Register ScratchReg = MRI.createVirtualRegister(&Xtensa::ARRegClass);
483+
auto II = MBB.end();
484+
485+
// Create l32r without last operand. We will add this operand later when
486+
// JumpToMMB will be calculated and placed to the ConstantPool.
487+
MachineInstr &L32R = *BuildMI(MBB, II, DL, get(Xtensa::L32R), ScratchReg);
488+
BuildMI(MBB, II, DL, get(Xtensa::JX)).addReg(ScratchReg, RegState::Kill);
489+
490+
RS->enterBasicBlockEnd(MBB);
491+
Register ScavRegister =
492+
RS->scavengeRegisterBackwards(Xtensa::ARRegClass, L32R.getIterator(),
493+
/*RestoreAfter=*/false, /*SpAdj=*/0,
494+
/*AllowSpill=*/false);
495+
if (ScavRegister != Xtensa::NoRegister)
496+
RS->setRegUsed(ScavRegister);
497+
else {
498+
// The case when there is no scavenged register needs special handling.
499+
// Pick A8 because it doesn't make a difference
500+
ScavRegister = Xtensa::A12;
501+
502+
int FrameIndex = XtensaFI->getBranchRelaxationScratchFrameIndex();
503+
if (FrameIndex == -1)
504+
report_fatal_error(
505+
"Unable to properly handle scavenged register for indirect jump, "
506+
"function code size is significantly larger than estimated");
507+
508+
storeRegToStackSlot(MBB, L32R, ScavRegister, /*IsKill=*/true, FrameIndex,
509+
&Xtensa::ARRegClass, &RI, Register());
510+
RI.eliminateFrameIndex(std::prev(L32R.getIterator()),
511+
/*SpAdj=*/0, /*FIOperandNum=*/1);
512+
513+
loadRegFromStackSlot(RestoreBB, RestoreBB.end(), ScavRegister, FrameIndex,
514+
&Xtensa::ARRegClass, &RI, Register());
515+
RI.eliminateFrameIndex(RestoreBB.back(),
516+
/*SpAdj=*/0, /*FIOperandNum=*/1);
517+
JumpToMBB = &RestoreBB;
518+
}
519+
520+
XtensaConstantPoolValue *C = XtensaConstantPoolMBB::Create(
521+
MF->getFunction().getContext(), JumpToMBB, 0);
522+
unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
523+
L32R.addOperand(MachineOperand::CreateCPI(Idx, 0));
524+
525+
MRI.replaceRegWith(ScratchReg, ScavRegister);
526+
MRI.clearVirtRegs();
527+
}
528+
529+
unsigned XtensaInstrInfo::insertConstBranchAtInst(
530+
MachineBasicBlock &MBB, MachineInstr *I, int64_t offset,
531+
ArrayRef<MachineOperand> Cond, DebugLoc DL, int *BytesAdded) const {
532+
// Shouldn't be a fall through.
533+
assert(&MBB && "InsertBranch must not be told to insert a fallthrough");
534+
assert(Cond.size() <= 4 &&
535+
"Xtensa branch conditions have less than four components!");
536+
537+
if (Cond.empty() || (Cond[0].getImm() == Xtensa::J)) {
538+
// Unconditional branch
539+
MachineInstr *MI = BuildMI(MBB, I, DL, get(Xtensa::J)).addImm(offset);
540+
if (BytesAdded && MI)
541+
*BytesAdded += getInstSizeInBytes(*MI);
542+
return 1;
543+
}
544+
545+
unsigned Count = 0;
546+
unsigned BR_C = Cond[0].getImm();
547+
MachineInstr *MI = nullptr;
548+
switch (BR_C) {
549+
case Xtensa::BEQ:
550+
case Xtensa::BNE:
551+
case Xtensa::BLT:
552+
case Xtensa::BLTU:
553+
case Xtensa::BGE:
554+
case Xtensa::BGEU:
555+
MI = BuildMI(MBB, I, DL, get(BR_C))
556+
.addImm(offset)
557+
.addReg(Cond[1].getReg())
558+
.addReg(Cond[2].getReg());
559+
break;
560+
case Xtensa::BEQI:
561+
case Xtensa::BNEI:
562+
case Xtensa::BLTI:
563+
case Xtensa::BLTUI:
564+
case Xtensa::BGEI:
565+
case Xtensa::BGEUI:
566+
MI = BuildMI(MBB, I, DL, get(BR_C))
567+
.addImm(offset)
568+
.addReg(Cond[1].getReg())
569+
.addImm(Cond[2].getImm());
570+
break;
571+
case Xtensa::BEQZ:
572+
case Xtensa::BNEZ:
573+
case Xtensa::BLTZ:
574+
case Xtensa::BGEZ:
575+
MI = BuildMI(MBB, I, DL, get(BR_C)).addImm(offset).addReg(Cond[1].getReg());
576+
break;
577+
default:
578+
llvm_unreachable("Invalid branch type!");
579+
}
580+
if (BytesAdded && MI)
581+
*BytesAdded += getInstSizeInBytes(*MI);
582+
++Count;
583+
return Count;
584+
}
585+
379586
unsigned XtensaInstrInfo::insertBranchAtInst(MachineBasicBlock &MBB,
380587
MachineBasicBlock::iterator I,
381588
MachineBasicBlock *TBB,

llvm/lib/Target/Xtensa/XtensaInstrInfo.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
3838
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
3939
MachineBasicBlock::iterator I) const;
4040

41+
unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
42+
4143
// Return the XtensaRegisterInfo, which this class owns.
4244
const XtensaRegisterInfo &getRegisterInfo() const { return RI; }
4345

@@ -77,6 +79,11 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
7779
bool
7880
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
7981

82+
MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
83+
84+
bool isBranchOffsetInRange(unsigned BranchOpc,
85+
int64_t BrOffset) const override;
86+
8087
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
8188
MachineBasicBlock *&FBB,
8289
SmallVectorImpl<MachineOperand> &Cond,
@@ -90,12 +97,22 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
9097
const DebugLoc &DL,
9198
int *BytesAdded = nullptr) const override;
9299

100+
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &DestBB,
101+
MachineBasicBlock &RestoreBB, const DebugLoc &DL,
102+
int64_t BrOffset = 0,
103+
RegScavenger *RS = nullptr) const override;
104+
93105
unsigned insertBranchAtInst(MachineBasicBlock &MBB,
94106
MachineBasicBlock::iterator I,
95107
MachineBasicBlock *TBB,
96108
ArrayRef<MachineOperand> Cond, const DebugLoc &DL,
97109
int *BytesAdded) const;
98110

111+
unsigned insertConstBranchAtInst(MachineBasicBlock &MBB, MachineInstr *I,
112+
int64_t offset,
113+
ArrayRef<MachineOperand> Cond, DebugLoc DL,
114+
int *BytesAdded) const;
115+
99116
// Return true if MI is a conditional or unconditional branch.
100117
// When returning true, set Cond to the mask of condition-code
101118
// values on which the instruction will branch, and set Target

0 commit comments

Comments
 (0)