[llvm] [Xtensa] Implement support for the BranchRelaxation. (PR #113450)
Andrei Safronov via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 30 06:30:09 PDT 2024
https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/113450
>From bf10a830d73050c25bb45529b5cfa40363343db6 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 23 Oct 2024 18:26:31 +0300
Subject: [PATCH 1/3] [Xtensa] Implement branch relaxation.
---
llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp | 3 +
.../lib/Target/Xtensa/XtensaFrameLowering.cpp | 32 ++-
llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp | 202 ++++++++++++++++++
llvm/lib/Target/Xtensa/XtensaInstrInfo.h | 17 ++
.../Target/Xtensa/XtensaMachineFunctionInfo.h | 42 ++++
llvm/lib/Target/Xtensa/XtensaRegisterInfo.h | 4 +
.../lib/Target/Xtensa/XtensaTargetMachine.cpp | 11 +
llvm/lib/Target/Xtensa/XtensaTargetMachine.h | 4 +
llvm/test/CodeGen/Xtensa/branch-relaxation.ll | 83 +++++++
llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll | 12 +-
10 files changed, 400 insertions(+), 10 deletions(-)
create mode 100644 llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
create mode 100644 llvm/test/CodeGen/Xtensa/branch-relaxation.ll
diff --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
index db86637ecf83f3..95dfafc13f3908 100644
--- a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
@@ -69,6 +69,9 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
const BlockAddress *BA =
cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress();
MCSym = GetBlockAddressSymbol(BA);
+ } else if (ACPV->isMachineBasicBlock()) {
+ const MachineBasicBlock *MBB = cast<XtensaConstantPoolMBB>(ACPV)->getMBB();
+ MCSym = MBB->getSymbol();
} else if (ACPV->isJumpTable()) {
unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex();
MCSym = this->GetJTISymbol(Idx, false);
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index f46d386c9186aa..ccdda31fa6fc06 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -12,6 +12,7 @@
#include "XtensaFrameLowering.h"
#include "XtensaInstrInfo.h"
+#include "XtensaMachineFunctionInfo.h"
#include "XtensaSubtarget.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -255,19 +256,42 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
SavedRegs.set(FP);
}
+static unsigned estimateFunctionSizeInBytes(const MachineFunction &MF,
+ const XtensaInstrInfo &TII) {
+ unsigned FnSize = 0;
+ for (auto &MBB : MF) {
+ for (auto &MI : MBB) {
+ FnSize += TII.getInstSizeInBytes(MI);
+ }
+ }
+ return FnSize;
+}
+
void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
MachineFunction &MF, RegScavenger *RS) const {
// Set scavenging frame index if necessary.
MachineFrameInfo &MFI = MF.getFrameInfo();
uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
+ auto *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
+ unsigned ScavSlotsNum = 0;
- if (isInt<12>(MaxSPOffset))
- return;
+ if (!isInt<12>(MaxSPOffset))
+ ScavSlotsNum = 1;
+
+ // Far branches over 18-bit offset require a spill slot for scratch register.
+ bool IsLargeFunction = !isInt<18>(estimateFunctionSizeInBytes(MF, TII));
+ if (IsLargeFunction)
+ ScavSlotsNum = std::max(ScavSlotsNum, 1u);
const TargetRegisterClass &RC = Xtensa::ARRegClass;
unsigned Size = TRI->getSpillSize(RC);
Align Alignment = TRI->getSpillAlign(RC);
- int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
+ for (unsigned I = 0; I < ScavSlotsNum; I++) {
+ int FI = MFI.CreateStackObject(Size, Alignment, false);
+ RS->addScavengingFrameIndex(FI);
- RS->addScavengingFrameIndex(FI);
+ if (IsLargeFunction &&
+ XtensaFI->getBranchRelaxationScratchFrameIndex() == -1)
+ XtensaFI->setBranchRelaxationScratchFrameIndex(FI);
+ }
}
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index b2b4376ca040b6..545467c527c1de 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -13,11 +13,14 @@
//===----------------------------------------------------------------------===//
#include "XtensaInstrInfo.h"
+#include "XtensaConstantPoolValue.h"
+#include "XtensaMachineFunctionInfo.h"
#include "XtensaTargetMachine.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
#define GET_INSTRINFO_CTOR_DTOR
#include "XtensaGenInstrInfo.inc"
@@ -186,6 +189,18 @@ void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
}
}
+unsigned XtensaInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ case TargetOpcode::INLINEASM: { // Inline Asm: Variable size.
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const char *AsmStr = MI.getOperand(0).getSymbolName();
+ return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
+ }
+ default:
+ return MI.getDesc().getSize();
+ }
+}
+
bool XtensaInstrInfo::reverseBranchCondition(
SmallVectorImpl<MachineOperand> &Cond) const {
assert(Cond.size() <= 4 && "Invalid branch condition!");
@@ -244,6 +259,74 @@ bool XtensaInstrInfo::reverseBranchCondition(
}
}
+MachineBasicBlock *
+XtensaInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
+ unsigned OpCode = MI.getOpcode();
+ switch (OpCode) {
+ case Xtensa::BR_JT:
+ case Xtensa::JX:
+ return nullptr;
+ case Xtensa::J:
+ return MI.getOperand(0).getMBB();
+ case Xtensa::BEQ:
+ case Xtensa::BNE:
+ case Xtensa::BLT:
+ case Xtensa::BLTU:
+ case Xtensa::BGE:
+ case Xtensa::BGEU:
+ return MI.getOperand(2).getMBB();
+ case Xtensa::BEQI:
+ case Xtensa::BNEI:
+ case Xtensa::BLTI:
+ case Xtensa::BLTUI:
+ case Xtensa::BGEI:
+ case Xtensa::BGEUI:
+ return MI.getOperand(2).getMBB();
+ case Xtensa::BEQZ:
+ case Xtensa::BNEZ:
+ case Xtensa::BLTZ:
+ case Xtensa::BGEZ:
+ return MI.getOperand(1).getMBB();
+ default:
+ llvm_unreachable("Unknown branch opcode");
+ }
+}
+
+bool XtensaInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
+ int64_t BrOffset) const {
+ switch (BranchOp) {
+ case Xtensa::J:
+ BrOffset -= 4;
+ return isIntN(18, BrOffset);
+ case Xtensa::JX:
+ return true;
+ case Xtensa::BR_JT:
+ return true;
+ case Xtensa::BEQ:
+ case Xtensa::BNE:
+ case Xtensa::BLT:
+ case Xtensa::BLTU:
+ case Xtensa::BGE:
+ case Xtensa::BGEU:
+ case Xtensa::BEQI:
+ case Xtensa::BNEI:
+ case Xtensa::BLTI:
+ case Xtensa::BLTUI:
+ case Xtensa::BGEI:
+ case Xtensa::BGEUI:
+ BrOffset -= 4;
+ return isIntN(8, BrOffset);
+ case Xtensa::BEQZ:
+ case Xtensa::BNEZ:
+ case Xtensa::BLTZ:
+ case Xtensa::BGEZ:
+ BrOffset -= 4;
+ return isIntN(12, BrOffset);
+ default:
+ llvm_unreachable("Unknown branch opcode");
+ }
+}
+
bool XtensaInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
@@ -376,6 +459,125 @@ unsigned XtensaInstrInfo::insertBranch(
return Count;
}
+void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock &DestBB,
+ MachineBasicBlock &RestoreBB,
+ const DebugLoc &DL, int64_t BrOffset,
+ RegScavenger *RS) const {
+ assert(RS && "RegScavenger required for long branching");
+ assert(MBB.empty() &&
+ "new block should be inserted for expanding unconditional branch");
+ assert(MBB.pred_size() == 1);
+
+ MachineFunction *MF = MBB.getParent();
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+ MachineConstantPool *ConstantPool = MF->getConstantPool();
+ auto *XtensaFI = MF->getInfo<XtensaMachineFunctionInfo>();
+
+ if (!isInt<32>(BrOffset))
+ report_fatal_error(
+ "Branch offsets outside of the signed 32-bit range not supported");
+
+ XtensaConstantPoolValue *C =
+ XtensaConstantPoolMBB::Create(MF->getFunction().getContext(), &DestBB, 0);
+ unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
+ Register ScratchReg = MRI.createVirtualRegister(&Xtensa::ARRegClass);
+ auto II = MBB.end();
+
+ MachineInstr &L32R = *BuildMI(MBB, II, DL, get(Xtensa::L32R), ScratchReg)
+ .addConstantPoolIndex(Idx);
+ BuildMI(MBB, II, DL, get(Xtensa::JX)).addReg(ScratchReg, RegState::Kill);
+
+ RS->enterBasicBlockEnd(MBB);
+ Register ScavRegister =
+ RS->scavengeRegisterBackwards(Xtensa::ARRegClass, L32R.getIterator(),
+ /*RestoreAfter=*/false, /*SpAdj=*/0,
+ /*AllowSpill=*/false);
+ if (ScavRegister != Xtensa::NoRegister)
+ RS->setRegUsed(ScavRegister);
+ else {
+ // The case when there is no scavenged register needs special handling.
+ // Pick A8 because it doesn't make a difference.
+ ScavRegister = Xtensa::A8;
+
+ int FrameIndex = XtensaFI->getBranchRelaxationScratchFrameIndex();
+ if (FrameIndex == -1)
+ report_fatal_error("underestimated function size");
+
+ storeRegToStackSlot(MBB, L32R, ScavRegister, /*IsKill=*/true, FrameIndex,
+ &Xtensa::ARRegClass, &RI, Register());
+ RI.eliminateFrameIndex(std::prev(L32R.getIterator()),
+ /*SpAdj=*/0, /*FIOperandNum=*/1);
+
+ L32R.getOperand(1).setMBB(&RestoreBB);
+
+ loadRegFromStackSlot(RestoreBB, RestoreBB.end(), ScavRegister, FrameIndex,
+ &Xtensa::ARRegClass, &RI, Register());
+ RI.eliminateFrameIndex(RestoreBB.back(),
+ /*SpAdj=*/0, /*FIOperandNum=*/1);
+ }
+
+ MRI.replaceRegWith(ScratchReg, ScavRegister);
+ MRI.clearVirtRegs();
+}
+
+unsigned XtensaInstrInfo::insertConstBranchAtInst(
+ MachineBasicBlock &MBB, MachineInstr *I, int64_t offset,
+ ArrayRef<MachineOperand> Cond, DebugLoc DL, int *BytesAdded) const {
+ // Shouldn't be a fall through.
+ assert(&MBB && "InsertBranch must not be told to insert a fallthrough");
+ assert(Cond.size() <= 4 &&
+ "Xtensa branch conditions have less than four components!");
+
+ if (Cond.empty() || (Cond[0].getImm() == Xtensa::J)) {
+ // Unconditional branch
+ MachineInstr *MI = BuildMI(MBB, I, DL, get(Xtensa::J)).addImm(offset);
+ if (BytesAdded && MI)
+ *BytesAdded += getInstSizeInBytes(*MI);
+ return 1;
+ }
+
+ unsigned Count = 0;
+ unsigned BR_C = Cond[0].getImm();
+ MachineInstr *MI = nullptr;
+ switch (BR_C) {
+ case Xtensa::BEQ:
+ case Xtensa::BNE:
+ case Xtensa::BLT:
+ case Xtensa::BLTU:
+ case Xtensa::BGE:
+ case Xtensa::BGEU:
+ MI = BuildMI(MBB, I, DL, get(BR_C))
+ .addImm(offset)
+ .addReg(Cond[1].getReg())
+ .addReg(Cond[2].getReg());
+ break;
+ case Xtensa::BEQI:
+ case Xtensa::BNEI:
+ case Xtensa::BLTI:
+ case Xtensa::BLTUI:
+ case Xtensa::BGEI:
+ case Xtensa::BGEUI:
+ MI = BuildMI(MBB, I, DL, get(BR_C))
+ .addImm(offset)
+ .addReg(Cond[1].getReg())
+ .addImm(Cond[2].getImm());
+ break;
+ case Xtensa::BEQZ:
+ case Xtensa::BNEZ:
+ case Xtensa::BLTZ:
+ case Xtensa::BGEZ:
+ MI = BuildMI(MBB, I, DL, get(BR_C)).addImm(offset).addReg(Cond[1].getReg());
+ break;
+ default:
+ llvm_unreachable("Invalid branch type!");
+ }
+ if (BytesAdded && MI)
+ *BytesAdded += getInstSizeInBytes(*MI);
+ ++Count;
+ return Count;
+}
+
unsigned XtensaInstrInfo::insertBranchAtInst(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
MachineBasicBlock *TBB,
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
index 9f45cf7c29ada7..31da4d481d3097 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
@@ -38,6 +38,8 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
+ unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
+
// Return the XtensaRegisterInfo, which this class owns.
const XtensaRegisterInfo &getRegisterInfo() const { return RI; }
@@ -77,6 +79,11 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
bool
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
+ MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
+
+ bool isBranchOffsetInRange(unsigned BranchOpc,
+ int64_t BrOffset) const override;
+
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
@@ -90,12 +97,22 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
const DebugLoc &DL,
int *BytesAdded = nullptr) const override;
+ void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &DestBB,
+ MachineBasicBlock &RestoreBB, const DebugLoc &DL,
+ int64_t BrOffset = 0,
+ RegScavenger *RS = nullptr) const override;
+
unsigned insertBranchAtInst(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
MachineBasicBlock *TBB,
ArrayRef<MachineOperand> Cond, const DebugLoc &DL,
int *BytesAdded) const;
+ unsigned insertConstBranchAtInst(MachineBasicBlock &MBB, MachineInstr *I,
+ int64_t offset,
+ ArrayRef<MachineOperand> Cond, DebugLoc DL,
+ int *BytesAdded) const;
+
// Return true if MI is a conditional or unconditional branch.
// When returning true, set Cond to the mask of condition-code
// values on which the instruction will branch, and set Target
diff --git a/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h b/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
new file mode 100644
index 00000000000000..c38c060b9387ff
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
@@ -0,0 +1,42 @@
+//==- XtensaMachineFunctionInfo.h - Xtensa machine function info --*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Xtensa-specific per-machine-function information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAMACHINEFUNCTIONINFO_H
+#define LLVM_LIB_TARGET_XTENSA_XTENSAMACHINEFUNCTIONINFO_H
+
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+
+class XtensaMachineFunctionInfo : public MachineFunctionInfo {
+ /// FrameIndex of the spill slot for the scratch register in BranchRelaxation.
+ int BranchRelaxationScratchFrameIndex = -1;
+
+public:
+ explicit XtensaMachineFunctionInfo(const Function &F,
+ const TargetSubtargetInfo *STI) {}
+
+ int getBranchRelaxationScratchFrameIndex() const {
+ return BranchRelaxationScratchFrameIndex;
+ }
+ void setBranchRelaxationScratchFrameIndex(int Index) {
+ BranchRelaxationScratchFrameIndex = Index;
+ }
+};
+
+} // namespace llvm
+
+#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAMACHINEFUNCTIONINFO_H */
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
index 8643ebb1c0f157..ede0eeb90b42de 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
@@ -38,6 +38,10 @@ class XtensaRegisterInfo : public XtensaGenRegisterInfo {
return true;
}
+ bool trackLivenessAfterRegAlloc(const MachineFunction &) const override {
+ return true;
+ }
+
const uint16_t *
getCalleeSavedRegs(const MachineFunction *MF = 0) const override;
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
diff --git a/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp b/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp
index 49c7faf84df1d3..8bbb2156e26904 100644
--- a/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp
@@ -14,6 +14,7 @@
#include "XtensaTargetMachine.h"
#include "TargetInfo/XtensaTargetInfo.h"
+#include "XtensaMachineFunctionInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -83,6 +84,13 @@ XtensaTargetMachine::getSubtargetImpl(const Function &F) const {
return I.get();
}
+MachineFunctionInfo *XtensaTargetMachine::createMachineFunctionInfo(
+ BumpPtrAllocator &Allocator, const Function &F,
+ const TargetSubtargetInfo *STI) const {
+ return XtensaMachineFunctionInfo::create<XtensaMachineFunctionInfo>(Allocator,
+ F, STI);
+}
+
namespace {
/// Xtensa Code Generator Pass Configuration Options.
class XtensaPassConfig : public TargetPassConfig {
@@ -95,6 +103,7 @@ class XtensaPassConfig : public TargetPassConfig {
}
bool addInstSelector() override;
+ void addPreEmitPass() override;
};
} // end anonymous namespace
@@ -103,6 +112,8 @@ bool XtensaPassConfig::addInstSelector() {
return false;
}
+void XtensaPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
+
TargetPassConfig *XtensaTargetMachine::createPassConfig(PassManagerBase &PM) {
return new XtensaPassConfig(*this, PM);
}
diff --git a/llvm/lib/Target/Xtensa/XtensaTargetMachine.h b/llvm/lib/Target/Xtensa/XtensaTargetMachine.h
index f371f22ed3d0e7..6975076b5d6997 100644
--- a/llvm/lib/Target/Xtensa/XtensaTargetMachine.h
+++ b/llvm/lib/Target/Xtensa/XtensaTargetMachine.h
@@ -45,6 +45,10 @@ class XtensaTargetMachine : public LLVMTargetMachine {
return TLOF.get();
}
+ MachineFunctionInfo *
+ createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
+ const TargetSubtargetInfo *STI) const override;
+
protected:
mutable StringMap<std::unique_ptr<XtensaSubtarget>> SubtargetMap;
};
diff --git a/llvm/test/CodeGen/Xtensa/branch-relaxation.ll b/llvm/test/CodeGen/Xtensa/branch-relaxation.ll
new file mode 100644
index 00000000000000..0b75f460c631a1
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/branch-relaxation.ll
@@ -0,0 +1,83 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc -mtriple=xtensa -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=XTENSA %s
+
+define i32 @jump(i1 %a) {
+; XTENSA-LABEL: jump:
+; XTENSA: movi a8, 1
+; XTENSA-NEXT: and a8, a2, a8
+; XTENSA-NEXT: beqz a8, .LBB0_2
+; XTENSA-NEXT: # %bb.1: # %iftrue
+; XTENSA-NEXT: #APP
+; XTENSA-NEXT: #NO_APP
+; XTENSA-NEXT: #APP
+; XTENSA-NEXT: .space 1024
+; XTENSA-NEXT: #NO_APP
+; XTENSA-NEXT: movi a2, 1
+; XTENSA-NEXT: ret
+; XTENSA-NEXT: .LBB0_2: # %jmp
+; XTENSA-NEXT: #APP
+; XTENSA-NEXT: #NO_APP
+; XTENSA-NEXT: movi a2, 1
+; XTENSA-NEXT: ret
+ br i1 %a, label %iftrue, label %jmp
+
+jmp:
+ call void asm sideeffect "", ""()
+ br label %tail
+
+iftrue:
+ call void asm sideeffect "", ""()
+ br label %space
+
+space:
+ call void asm sideeffect ".space 1024", ""()
+ br label %tail
+
+tail:
+ ret i32 1
+}
+
+define i32 @jx(i1 %a) {
+; XTENSA-LABEL: jx:
+; XTENSA: addi a8, a1, -16
+; XTENSA-NEXT: or a1, a8, a8
+; XTENSA-NEXT: .cfi_def_cfa_offset 16
+; XTENSA-NEXT: movi a8, 1
+; XTENSA-NEXT: and a8, a2, a8
+; XTENSA-NEXT: bnez a8, .LBB1_1
+; XTENSA-NEXT: # %bb.4:
+; XTENSA-NEXT: l32r a8, .LCPI1_0
+; XTENSA-NEXT: jx a8
+; XTENSA-NEXT: .LBB1_1: # %iftrue
+; XTENSA-NEXT: #APP
+; XTENSA-NEXT: #NO_APP
+; XTENSA-NEXT: #APP
+; XTENSA-NEXT: .space 1048576
+; XTENSA-NEXT: #NO_APP
+; XTENSA-NEXT: j .LBB1_3
+; XTENSA-NEXT: .LBB1_2: # %jmp
+; XTENSA-NEXT: #APP
+; XTENSA-NEXT: #NO_APP
+; XTENSA-NEXT: .LBB1_3: # %tail
+; XTENSA-NEXT: movi a2, 1
+; XTENSA-NEXT: addi a8, a1, 16
+; XTENSA-NEXT: or a1, a8, a8
+; XTENSA-NEXT: ret
+ br i1 %a, label %iftrue, label %jmp
+
+jmp:
+ call void asm sideeffect "", ""()
+ br label %tail
+
+iftrue:
+ call void asm sideeffect "", ""()
+ br label %space
+
+space:
+ call void asm sideeffect ".space 1048576", ""()
+ br label %tail
+
+tail:
+ ret i32 1
+}
diff --git a/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
index bad57d58b28a67..60303235386256 100644
--- a/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
+++ b/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
@@ -8,8 +8,8 @@ declare i32 @llvm.ctpop.i32(i32)
define i32 @test_cttz_i32(i32 %a) nounwind {
; XTENSA-LABEL: test_cttz_i32:
-; XTENSA: beqz a2, .LBB0_1
-; XTENSA-NEXT: # %bb.2: # %cond.false
+; XTENSA: beqz a2, .LBB0_2
+; XTENSA-NEXT: # %bb.1: # %cond.false
; XTENSA-NEXT: movi a8, -1
; XTENSA-NEXT: xor a8, a2, a8
; XTENSA-NEXT: addi a9, a2, -1
@@ -33,7 +33,7 @@ define i32 @test_cttz_i32(i32 %a) nounwind {
; XTENSA-NEXT: add a8, a8, a9
; XTENSA-NEXT: extui a2, a8, 24, 8
; XTENSA-NEXT: ret
-; XTENSA-NEXT: .LBB0_1:
+; XTENSA-NEXT: .LBB0_2:
; XTENSA-NEXT: movi a2, 32
; XTENSA-NEXT: ret
%tmp = call i32 @llvm.cttz.i32(i32 %a, i1 false)
@@ -71,8 +71,8 @@ define i32 @test_cttz_i32_zero_undef(i32 %a) nounwind {
define i32 @test_ctlz_i32(i32 %a) nounwind {
; XTENSA-LABEL: test_ctlz_i32:
-; XTENSA: beqz a2, .LBB2_1
-; XTENSA-NEXT: # %bb.2: # %cond.false
+; XTENSA: beqz a2, .LBB2_2
+; XTENSA-NEXT: # %bb.1: # %cond.false
; XTENSA-NEXT: srli a8, a2, 1
; XTENSA-NEXT: or a8, a2, a8
; XTENSA-NEXT: srli a9, a8, 2
@@ -104,7 +104,7 @@ define i32 @test_ctlz_i32(i32 %a) nounwind {
; XTENSA-NEXT: add a8, a8, a9
; XTENSA-NEXT: extui a2, a8, 24, 8
; XTENSA-NEXT: ret
-; XTENSA-NEXT: .LBB2_1:
+; XTENSA-NEXT: .LBB2_2:
; XTENSA-NEXT: movi a2, 32
; XTENSA-NEXT: ret
%tmp = call i32 @llvm.ctlz.i32(i32 %a, i1 false)
>From 25ba0cbabf0711e88d8f3b9c9b6f82f779268bb1 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Tue, 29 Oct 2024 19:42:33 +0300
Subject: [PATCH 2/3] [Xtensa] Fix insertIndirectBranch and
estimateFunctionSizeInBytes functions.
---
.../lib/Target/Xtensa/XtensaFrameLowering.cpp | 25 ++++++++++++++++---
llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp | 19 ++++++++------
2 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index ccdda31fa6fc06..4ceb67d082532b 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -258,13 +258,32 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
static unsigned estimateFunctionSizeInBytes(const MachineFunction &MF,
const XtensaInstrInfo &TII) {
- unsigned FnSize = 0;
+ const Align FunctiontAlignment = MF.getAlignment();
+ /// Offset - Distance from the beginning of the function to the end
+ /// of the basic block.
+ unsigned Offset = 0;
+
for (auto &MBB : MF) {
+ const Align Alignment = MBB.getAlignment();
+ unsigned BlockSize = 0;
+
for (auto &MI : MBB) {
- FnSize += TII.getInstSizeInBytes(MI);
+ BlockSize += TII.getInstSizeInBytes(MI);
}
+
+ unsigned OffsetBB;
+ if (Alignment <= FunctiontAlignment) {
+ OffsetBB = alignTo(Offset, Alignment);
+ } else {
+ // The alignment of this MBB is larger than the function's alignment, so
+ // we can't tell whether or not it will insert nops. Assume that it will.
+ OffsetBB = alignTo(Offset, Alignment) + Alignment.value() -
+ FunctiontAlignment.value();
+ }
+ Offset = OffsetBB + BlockSize;
}
- return FnSize;
+
+ return Offset;
}
void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 545467c527c1de..cd20838f56d832 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -473,19 +473,18 @@ void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
MachineRegisterInfo &MRI = MF->getRegInfo();
MachineConstantPool *ConstantPool = MF->getConstantPool();
auto *XtensaFI = MF->getInfo<XtensaMachineFunctionInfo>();
+ MachineBasicBlock *JumpToMBB = &DestBB;
if (!isInt<32>(BrOffset))
report_fatal_error(
"Branch offsets outside of the signed 32-bit range not supported");
- XtensaConstantPoolValue *C =
- XtensaConstantPoolMBB::Create(MF->getFunction().getContext(), &DestBB, 0);
- unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
Register ScratchReg = MRI.createVirtualRegister(&Xtensa::ARRegClass);
auto II = MBB.end();
- MachineInstr &L32R = *BuildMI(MBB, II, DL, get(Xtensa::L32R), ScratchReg)
- .addConstantPoolIndex(Idx);
+ // Create l32r without last operand. We will add this operand later when
+ // JumpToMMB will be calculated and placed to the ConstantPool.
+ MachineInstr &L32R = *BuildMI(MBB, II, DL, get(Xtensa::L32R), ScratchReg);
BuildMI(MBB, II, DL, get(Xtensa::JX)).addReg(ScratchReg, RegState::Kill);
RS->enterBasicBlockEnd(MBB);
@@ -497,7 +496,7 @@ void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
RS->setRegUsed(ScavRegister);
else {
// The case when there is no scavenged register needs special handling.
- // Pick A8 because it doesn't make a difference.
+ // Pick A8 because it doesn't make a difference
ScavRegister = Xtensa::A8;
int FrameIndex = XtensaFI->getBranchRelaxationScratchFrameIndex();
@@ -509,14 +508,18 @@ void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
RI.eliminateFrameIndex(std::prev(L32R.getIterator()),
/*SpAdj=*/0, /*FIOperandNum=*/1);
- L32R.getOperand(1).setMBB(&RestoreBB);
-
loadRegFromStackSlot(RestoreBB, RestoreBB.end(), ScavRegister, FrameIndex,
&Xtensa::ARRegClass, &RI, Register());
RI.eliminateFrameIndex(RestoreBB.back(),
/*SpAdj=*/0, /*FIOperandNum=*/1);
+ JumpToMBB = &RestoreBB;
}
+ XtensaConstantPoolValue *C = XtensaConstantPoolMBB::Create(
+ MF->getFunction().getContext(), JumpToMBB, 0);
+ unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
+ L32R.addOperand(MachineOperand::CreateCPI(Idx, 0));
+
MRI.replaceRegWith(ScratchReg, ScavRegister);
MRI.clearVirtRegs();
}
>From e3ef765a85c0fe21f93fdb0a7b6c8bd0532b6407 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 30 Oct 2024 16:28:28 +0300
Subject: [PATCH 3/3] [PATCH] [Xtensa] Minor fixes.
---
.../lib/Target/Xtensa/XtensaFrameLowering.cpp | 31 +------------------
llvm/lib/Target/Xtensa/XtensaUtils.cpp | 30 ++++++++++++++++++
llvm/lib/Target/Xtensa/XtensaUtils.h | 3 ++
3 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 4ceb67d082532b..8f1cbf6b934390 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -14,6 +14,7 @@
#include "XtensaInstrInfo.h"
#include "XtensaMachineFunctionInfo.h"
#include "XtensaSubtarget.h"
+#include "XtensaUtils.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
@@ -256,36 +257,6 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
SavedRegs.set(FP);
}
-static unsigned estimateFunctionSizeInBytes(const MachineFunction &MF,
- const XtensaInstrInfo &TII) {
- const Align FunctiontAlignment = MF.getAlignment();
- /// Offset - Distance from the beginning of the function to the end
- /// of the basic block.
- unsigned Offset = 0;
-
- for (auto &MBB : MF) {
- const Align Alignment = MBB.getAlignment();
- unsigned BlockSize = 0;
-
- for (auto &MI : MBB) {
- BlockSize += TII.getInstSizeInBytes(MI);
- }
-
- unsigned OffsetBB;
- if (Alignment <= FunctiontAlignment) {
- OffsetBB = alignTo(Offset, Alignment);
- } else {
- // The alignment of this MBB is larger than the function's alignment, so
- // we can't tell whether or not it will insert nops. Assume that it will.
- OffsetBB = alignTo(Offset, Alignment) + Alignment.value() -
- FunctiontAlignment.value();
- }
- Offset = OffsetBB + BlockSize;
- }
-
- return Offset;
-}
-
void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
MachineFunction &MF, RegScavenger *RS) const {
// Set scavenging frame index if necessary.
diff --git a/llvm/lib/Target/Xtensa/XtensaUtils.cpp b/llvm/lib/Target/Xtensa/XtensaUtils.cpp
index 98e424f6ea4406..e5d95bf3b195d3 100644
--- a/llvm/lib/Target/Xtensa/XtensaUtils.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaUtils.cpp
@@ -56,4 +56,34 @@ bool isValidAddrOffset(MachineInstr &MI, int64_t Offset) {
return isValidAddrOffset(Scale, Offset);
}
+int64_t estimateFunctionSizeInBytes(const MachineFunction &MF,
+ const XtensaInstrInfo &TII) {
+ const Align FunctionAlignment = MF.getAlignment();
+ /// Offset - Distance from the beginning of the function to the end
+ /// of the basic block.
+ int64_t Offset = 0;
+
+ for (auto &MBB : MF) {
+ const Align Alignment = MBB.getAlignment();
+ int64_t BlockSize = 0;
+
+ for (auto &MI : MBB) {
+ BlockSize += TII.getInstSizeInBytes(MI);
+ }
+
+ int64_t OffsetBB;
+ if (Alignment <= FunctionAlignment) {
+ OffsetBB = alignTo(Offset, Alignment);
+ } else {
+ // The alignment of this MBB is larger than the function's alignment, so
+ // we can't tell whether or not it will insert nops. Assume that it will.
+ OffsetBB = alignTo(Offset, Alignment) + Alignment.value() -
+ FunctionAlignment.value();
+ }
+ Offset = OffsetBB + BlockSize;
+ }
+
+ return Offset;
+}
+
} // namespace llvm
diff --git a/llvm/lib/Target/Xtensa/XtensaUtils.h b/llvm/lib/Target/Xtensa/XtensaUtils.h
index 2b0ac37a6971a1..63c692e79dfbc1 100644
--- a/llvm/lib/Target/Xtensa/XtensaUtils.h
+++ b/llvm/lib/Target/Xtensa/XtensaUtils.h
@@ -23,5 +23,8 @@ bool isValidAddrOffset(int Scale, int64_t OffsetVal);
// Check address offset for load/store instructions.
bool isValidAddrOffset(MachineInstr &MI, int64_t Offset);
+
+int64_t estimateFunctionSizeInBytes(const MachineFunction &MF,
+ const XtensaInstrInfo &TII);
} // namespace llvm
#endif // LLVM_LIB_TARGET_XTENSA_XTENSAUTILS_H
More information about the llvm-commits
mailing list