Skip to content

Commit 77d3f45

Browse files
committed
[Xtensa] Implement support for the BranchRelaxation.
1 parent 9b88792 commit 77d3f45

10 files changed

+399
-10
lines changed

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: 27 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"
@@ -255,19 +256,41 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
255256
SavedRegs.set(FP);
256257
}
257258

259+
static unsigned estimateFunctionSizeInBytes(const MachineFunction &MF,
260+
const XtensaInstrInfo &TII) {
261+
unsigned FnSize = 0;
262+
for (auto &MBB : MF) {
263+
for (auto &MI : MBB) {
264+
FnSize += TII.getInstSizeInBytes(MI);
265+
}
266+
}
267+
return FnSize;
268+
}
269+
258270
void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
259271
MachineFunction &MF, RegScavenger *RS) const {
260272
// Set scavenging frame index if necessary.
261273
MachineFrameInfo &MFI = MF.getFrameInfo();
262274
uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
275+
auto *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
276+
unsigned ScavSlotsNum = 0;
263277

264-
if (isInt<12>(MaxSPOffset))
265-
return;
278+
if (!isInt<12>(MaxSPOffset))
279+
ScavSlotsNum = 1;
280+
281+
// Far branches over 18-bit offset require a spill slot for scratch register.
282+
bool IsLargeFunction = !isInt<18>(estimateFunctionSizeInBytes(MF, TII));
283+
if (IsLargeFunction)
284+
ScavSlotsNum = std::max(ScavSlotsNum, 1u);
266285

267286
const TargetRegisterClass &RC = Xtensa::ARRegClass;
268287
unsigned Size = TRI->getSpillSize(RC);
269288
Align Alignment = TRI->getSpillAlign(RC);
270-
int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
289+
for (unsigned I = 0; I < ScavSlotsNum; I++) {
290+
int FI = MFI.CreateStackObject(Size, Alignment, false);
291+
RS->addScavengingFrameIndex(FI);
271292

272-
RS->addScavengingFrameIndex(FI);
293+
if (IsLargeFunction && XtensaFI->getBranchRelaxationScratchFrameIndex() == -1)
294+
XtensaFI->setBranchRelaxationScratchFrameIndex(FI);
295+
}
273296
}

llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp

Lines changed: 202 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,125 @@ 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+
477+
if (!isInt<32>(BrOffset))
478+
report_fatal_error(
479+
"Branch offsets outside of the signed 32-bit range not supported");
480+
481+
XtensaConstantPoolValue *C =
482+
XtensaConstantPoolMBB::Create(MF->getFunction().getContext(), &DestBB, 0);
483+
unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
484+
Register ScratchReg = MRI.createVirtualRegister(&Xtensa::ARRegClass);
485+
auto II = MBB.end();
486+
487+
MachineInstr &L32R = *BuildMI(MBB, II, DL, get(Xtensa::L32R), ScratchReg)
488+
.addConstantPoolIndex(Idx);
489+
BuildMI(MBB, II, DL, get(Xtensa::JX)).addReg(ScratchReg, RegState::Kill);
490+
491+
RS->enterBasicBlockEnd(MBB);
492+
Register ScavRegister =
493+
RS->scavengeRegisterBackwards(Xtensa::ARRegClass, L32R.getIterator(),
494+
/*RestoreAfter=*/false, /*SpAdj=*/0,
495+
/*AllowSpill=*/false);
496+
if (ScavRegister != Xtensa::NoRegister)
497+
RS->setRegUsed(ScavRegister);
498+
else {
499+
// The case when there is no scavenged register needs special handling.
500+
// Pick A8 because it doesn't make a difference.
501+
ScavRegister = Xtensa::A8;
502+
503+
int FrameIndex = XtensaFI->getBranchRelaxationScratchFrameIndex();
504+
if (FrameIndex == -1)
505+
report_fatal_error("underestimated function size");
506+
507+
storeRegToStackSlot(MBB, L32R, ScavRegister, /*IsKill=*/true, FrameIndex,
508+
&Xtensa::ARRegClass, &RI, Register());
509+
RI.eliminateFrameIndex(std::prev(L32R.getIterator()),
510+
/*SpAdj=*/0, /*FIOperandNum=*/1);
511+
512+
L32R.getOperand(1).setMBB(&RestoreBB);
513+
514+
loadRegFromStackSlot(RestoreBB, RestoreBB.end(), ScavRegister, FrameIndex,
515+
&Xtensa::ARRegClass, &RI, Register());
516+
RI.eliminateFrameIndex(RestoreBB.back(),
517+
/*SpAdj=*/0, /*FIOperandNum=*/1);
518+
}
519+
520+
MRI.replaceRegWith(ScratchReg, ScavRegister);
521+
MRI.clearVirtRegs();
522+
}
523+
524+
unsigned XtensaInstrInfo::insertConstBranchAtInst(
525+
MachineBasicBlock &MBB, MachineInstr *I, int64_t offset,
526+
ArrayRef<MachineOperand> Cond, DebugLoc DL, int *BytesAdded) const {
527+
// Shouldn't be a fall through.
528+
assert(&MBB && "InsertBranch must not be told to insert a fallthrough");
529+
assert(Cond.size() <= 4 &&
530+
"Xtensa branch conditions have less than four components!");
531+
532+
if (Cond.empty() || (Cond[0].getImm() == Xtensa::J)) {
533+
// Unconditional branch
534+
MachineInstr *MI = BuildMI(MBB, I, DL, get(Xtensa::J)).addImm(offset);
535+
if (BytesAdded && MI)
536+
*BytesAdded += getInstSizeInBytes(*MI);
537+
return 1;
538+
}
539+
540+
unsigned Count = 0;
541+
unsigned BR_C = Cond[0].getImm();
542+
MachineInstr *MI = nullptr;
543+
switch (BR_C) {
544+
case Xtensa::BEQ:
545+
case Xtensa::BNE:
546+
case Xtensa::BLT:
547+
case Xtensa::BLTU:
548+
case Xtensa::BGE:
549+
case Xtensa::BGEU:
550+
MI = BuildMI(MBB, I, DL, get(BR_C))
551+
.addImm(offset)
552+
.addReg(Cond[1].getReg())
553+
.addReg(Cond[2].getReg());
554+
break;
555+
case Xtensa::BEQI:
556+
case Xtensa::BNEI:
557+
case Xtensa::BLTI:
558+
case Xtensa::BLTUI:
559+
case Xtensa::BGEI:
560+
case Xtensa::BGEUI:
561+
MI = BuildMI(MBB, I, DL, get(BR_C))
562+
.addImm(offset)
563+
.addReg(Cond[1].getReg())
564+
.addImm(Cond[2].getImm());
565+
break;
566+
case Xtensa::BEQZ:
567+
case Xtensa::BNEZ:
568+
case Xtensa::BLTZ:
569+
case Xtensa::BGEZ:
570+
MI = BuildMI(MBB, I, DL, get(BR_C)).addImm(offset).addReg(Cond[1].getReg());
571+
break;
572+
default:
573+
llvm_unreachable("Invalid branch type!");
574+
}
575+
if (BytesAdded && MI)
576+
*BytesAdded += getInstSizeInBytes(*MI);
577+
++Count;
578+
return Count;
579+
}
580+
379581
unsigned XtensaInstrInfo::insertBranchAtInst(MachineBasicBlock &MBB,
380582
MachineBasicBlock::iterator I,
381583
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
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//==- XtensaMachineFunctionInfo.h - Xtensa machine function info --*- C++ -*-=//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6+
// See https://llvm.org/LICENSE.txt for license information.
7+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
//
9+
//===----------------------------------------------------------------------===//
10+
//
11+
// This file declares Xtensa-specific per-machine-function information.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAMACHINEFUNCTIONINFO_H
16+
#define LLVM_LIB_TARGET_XTENSA_XTENSAMACHINEFUNCTIONINFO_H
17+
18+
#include "llvm/CodeGen/MachineFrameInfo.h"
19+
#include "llvm/CodeGen/MachineFunction.h"
20+
#include "llvm/Target/TargetMachine.h"
21+
22+
namespace llvm {
23+
24+
class XtensaMachineFunctionInfo : public MachineFunctionInfo {
25+
/// FrameIndex of the spill slot for the scratch register in BranchRelaxation.
26+
int BranchRelaxationScratchFrameIndex = -1;
27+
28+
public:
29+
explicit XtensaMachineFunctionInfo(const Function &F,
30+
const TargetSubtargetInfo *STI) {}
31+
32+
int getBranchRelaxationScratchFrameIndex() const {
33+
return BranchRelaxationScratchFrameIndex;
34+
}
35+
void setBranchRelaxationScratchFrameIndex(int Index) {
36+
BranchRelaxationScratchFrameIndex = Index;
37+
}
38+
};
39+
40+
} // namespace llvm
41+
42+
#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAMACHINEFUNCTIONINFO_H */

llvm/lib/Target/Xtensa/XtensaRegisterInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ class XtensaRegisterInfo : public XtensaGenRegisterInfo {
3838
return true;
3939
}
4040

41+
bool trackLivenessAfterRegAlloc(const MachineFunction &) const override {
42+
return true;
43+
}
44+
4145
const uint16_t *
4246
getCalleeSavedRegs(const MachineFunction *MF = 0) const override;
4347
const uint32_t *getCallPreservedMask(const MachineFunction &MF,

0 commit comments

Comments
 (0)