[llvm] [Xtensa] Implement branch relaxation. (PR #110959)

Andrei Safronov via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 10 16:53:21 PDT 2024


https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/110959

>From 2b1a8b11349bc1ff82bcc61a987fe81cd0278f3c Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 3 Oct 2024 09:14:38 +0300
Subject: [PATCH 1/2] [Xtensa] Implement branch analysis.

---
 llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp   |   3 +
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp    | 478 ++++++++++++++++++
 llvm/lib/Target/Xtensa/XtensaInstrInfo.h      |  48 ++
 llvm/lib/Target/Xtensa/XtensaInstrInfo.td     |   2 +
 llvm/lib/Target/Xtensa/XtensaRegisterInfo.h   |   4 +
 .../lib/Target/Xtensa/XtensaTargetMachine.cpp |   3 +
 llvm/test/CodeGen/Xtensa/branch-relaxation.ll |  42 ++
 llvm/test/CodeGen/Xtensa/branch.ll            | 139 +++++
 llvm/test/CodeGen/Xtensa/brcc.ll              |  61 +--
 llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll   |  28 +-
 llvm/test/CodeGen/Xtensa/select-cc.ll         |   9 +-
 11 files changed, 757 insertions(+), 60 deletions(-)
 create mode 100644 llvm/test/CodeGen/Xtensa/branch-relaxation.ll
 create mode 100644 llvm/test/CodeGen/Xtensa/branch.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/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 2263aadcb0dd3f..c944ea52533fcb 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -13,11 +13,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "XtensaInstrInfo.h"
+#include "XtensaConstantPoolValue.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"
@@ -185,3 +187,479 @@ void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
     report_fatal_error("Unsupported load immediate value");
   }
 }
+
+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!");
+
+  switch (Cond[0].getImm()) {
+  case Xtensa::BEQ:
+    Cond[0].setImm(Xtensa::BNE);
+    return false;
+  case Xtensa::BNE:
+    Cond[0].setImm(Xtensa::BEQ);
+    return false;
+  case Xtensa::BLT:
+    Cond[0].setImm(Xtensa::BGE);
+    return false;
+  case Xtensa::BGE:
+    Cond[0].setImm(Xtensa::BLT);
+    return false;
+  case Xtensa::BLTU:
+    Cond[0].setImm(Xtensa::BGEU);
+    return false;
+  case Xtensa::BGEU:
+    Cond[0].setImm(Xtensa::BLTU);
+    return false;
+
+  case Xtensa::BEQI:
+    Cond[0].setImm(Xtensa::BNEI);
+    return false;
+  case Xtensa::BNEI:
+    Cond[0].setImm(Xtensa::BEQI);
+    return false;
+  case Xtensa::BGEI:
+    Cond[0].setImm(Xtensa::BLTI);
+    return false;
+  case Xtensa::BLTI:
+    Cond[0].setImm(Xtensa::BGEI);
+    return false;
+  case Xtensa::BGEUI:
+    Cond[0].setImm(Xtensa::BLTUI);
+    return false;
+  case Xtensa::BLTUI:
+    Cond[0].setImm(Xtensa::BGEUI);
+    return false;
+
+  case Xtensa::BEQZ:
+    Cond[0].setImm(Xtensa::BNEZ);
+    return false;
+  case Xtensa::BNEZ:
+    Cond[0].setImm(Xtensa::BEQZ);
+    return false;
+  case Xtensa::BLTZ:
+    Cond[0].setImm(Xtensa::BGEZ);
+    return false;
+  case Xtensa::BGEZ:
+    Cond[0].setImm(Xtensa::BLTZ);
+    return false;
+
+  default:
+    report_fatal_error("Invalid branch condition!");
+  }
+}
+
+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,
+                                    SmallVectorImpl<MachineOperand> &Cond,
+                                    bool AllowModify = false) const {
+  // Most of the code and comments here are boilerplate.
+
+  // Start from the bottom of the block and work up, examining the
+  // terminator instructions.
+  MachineBasicBlock::iterator I = MBB.end();
+  while (I != MBB.begin()) {
+    --I;
+    if (I->isDebugValue())
+      continue;
+
+    // Working from the bottom, when we see a non-terminator instruction, we're
+    // done.
+    if (!isUnpredicatedTerminator(*I))
+      break;
+
+    // A terminator that isn't a branch can't easily be handled by this
+    // analysis.
+    SmallVector<MachineOperand, 4> ThisCond;
+    ThisCond.push_back(MachineOperand::CreateImm(0));
+    const MachineOperand *ThisTarget;
+    if (!isBranch(I, ThisCond, ThisTarget))
+      return true;
+
+    // Can't handle indirect branches.
+    if (!ThisTarget->isMBB())
+      return true;
+
+    if (ThisCond[0].getImm() == Xtensa::J) {
+      // Handle unconditional branches.
+      if (!AllowModify) {
+        TBB = ThisTarget->getMBB();
+        continue;
+      }
+
+      // If the block has any instructions after a JMP, delete them.
+      while (std::next(I) != MBB.end())
+        std::next(I)->eraseFromParent();
+
+      Cond.clear();
+      FBB = 0;
+
+      // TBB is used to indicate the unconditinal destination.
+      TBB = ThisTarget->getMBB();
+      continue;
+    }
+
+    // Working from the bottom, handle the first conditional branch.
+    if (Cond.empty()) {
+      // FIXME: add X86-style branch swap
+      FBB = TBB;
+      TBB = ThisTarget->getMBB();
+      Cond.push_back(MachineOperand::CreateImm(ThisCond[0].getImm()));
+
+      // push remaining operands
+      for (unsigned int i = 0; i < (I->getNumExplicitOperands() - 1); i++)
+        Cond.push_back(I->getOperand(i));
+
+      continue;
+    }
+
+    // Handle subsequent conditional branches.
+    assert(Cond.size() <= 4);
+    assert(TBB);
+
+    // Only handle the case where all conditional branches branch to the same
+    // destination.
+    if (TBB != ThisTarget->getMBB())
+      return true;
+
+    // If the conditions are the same, we can leave them alone.
+    unsigned OldCond = Cond[0].getImm();
+    if (OldCond == ThisCond[0].getImm())
+      continue;
+  }
+
+  return false;
+}
+
+unsigned XtensaInstrInfo::removeBranch(MachineBasicBlock &MBB,
+                                       int *BytesRemoved) const {
+  // Most of the code and comments here are boilerplate.
+  MachineBasicBlock::iterator I = MBB.end();
+  unsigned Count = 0;
+  if (BytesRemoved)
+    *BytesRemoved = 0;
+
+  while (I != MBB.begin()) {
+    --I;
+    SmallVector<MachineOperand, 4> Cond;
+    Cond.push_back(MachineOperand::CreateImm(0));
+    const MachineOperand *Target;
+    if (!isBranch(I, Cond, Target))
+      break;
+    if (!Target->isMBB())
+      break;
+    // Remove the branch.
+    if (BytesRemoved)
+      *BytesRemoved += getInstSizeInBytes(*I);
+    I->eraseFromParent();
+    I = MBB.end();
+    ++Count;
+  }
+  return Count;
+}
+
+unsigned XtensaInstrInfo::insertBranch(
+    MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+    ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
+  unsigned Count = 0;
+  if (BytesAdded)
+    *BytesAdded = 0;
+  if (FBB) {
+    // Need to build two branches then
+    // one to branch to TBB on Cond
+    // and a second one immediately after to unconditionally jump to FBB
+    Count = InsertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded);
+    auto &MI = *BuildMI(&MBB, DL, get(Xtensa::J)).addMBB(FBB);
+    Count++;
+    if (BytesAdded)
+      *BytesAdded += getInstSizeInBytes(MI);
+    return Count;
+  }
+  // This function inserts the branch at the end of the MBB
+  Count += InsertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded);
+  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();
+
+  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));
+
+  // FIXME: A virtual register must be used initially, as the register
+  // scavenger won't work with empty blocks (SIInstrInfo::insertIndirectBranch
+  // uses the same workaround).
+  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);
+  unsigned Scav = RS->scavengeRegisterBackwards(Xtensa::ARRegClass,
+                                                L32R.getIterator(), false, 0);
+  MRI.replaceRegWith(ScratchReg, Scav);
+  MRI.clearVirtRegs();
+  RS->setRegUsed(Scav);
+}
+
+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,
+                                             ArrayRef<MachineOperand> Cond,
+                                             const DebugLoc &DL,
+                                             int *BytesAdded) const {
+  // Shouldn't be a fall through.
+  assert(TBB && "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)).addMBB(TBB);
+    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))
+             .addReg(Cond[1].getReg())
+             .addReg(Cond[2].getReg())
+             .addMBB(TBB);
+    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))
+             .addReg(Cond[1].getReg())
+             .addImm(Cond[2].getImm())
+             .addMBB(TBB);
+    break;
+  case Xtensa::BEQZ:
+  case Xtensa::BNEZ:
+  case Xtensa::BLTZ:
+  case Xtensa::BGEZ:
+    MI = BuildMI(MBB, I, DL, get(BR_C)).addReg(Cond[1].getReg()).addMBB(TBB);
+    break;
+  default:
+    report_fatal_error("Invalid branch type!");
+  }
+  if (BytesAdded && MI)
+    *BytesAdded += getInstSizeInBytes(*MI);
+  ++Count;
+  return Count;
+}
+
+bool XtensaInstrInfo::isBranch(const MachineBasicBlock::iterator &MI,
+                               SmallVectorImpl<MachineOperand> &Cond,
+                               const MachineOperand *&Target) const {
+  unsigned OpCode = MI->getOpcode();
+  switch (OpCode) {
+  case Xtensa::J:
+  case Xtensa::JX:
+  case Xtensa::BR_JT:
+    Cond[0].setImm(OpCode);
+    Target = &MI->getOperand(0);
+    return true;
+  case Xtensa::BEQ:
+  case Xtensa::BNE:
+  case Xtensa::BLT:
+  case Xtensa::BLTU:
+  case Xtensa::BGE:
+  case Xtensa::BGEU:
+    Cond[0].setImm(OpCode);
+    Target = &MI->getOperand(2);
+    return true;
+
+  case Xtensa::BEQI:
+  case Xtensa::BNEI:
+  case Xtensa::BLTI:
+  case Xtensa::BLTUI:
+  case Xtensa::BGEI:
+  case Xtensa::BGEUI:
+    Cond[0].setImm(OpCode);
+    Target = &MI->getOperand(2);
+    return true;
+
+  case Xtensa::BEQZ:
+  case Xtensa::BNEZ:
+  case Xtensa::BLTZ:
+  case Xtensa::BGEZ:
+    Cond[0].setImm(OpCode);
+    Target = &MI->getOperand(1);
+    return true;
+
+  default:
+    assert(!MI->getDesc().isBranch() && "Unknown branch opcode");
+    return false;
+  }
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
index 8bf3f0618f2857..ce9484a89751dd 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; }
 
@@ -74,6 +76,52 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
   void loadImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
                      unsigned *Reg, int64_t Value) const;
 
+  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,
+                     bool AllowModify) const override;
+
+  unsigned removeBranch(MachineBasicBlock &MBB,
+                        int *BytesRemoved = nullptr) const override;
+
+  unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+                        MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
+                        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
+  // to the operand that contains the branch target.  This target
+  // can be a register or a basic block.
+  bool isBranch(const MachineBasicBlock::iterator &MI,
+                SmallVectorImpl<MachineOperand> &Cond,
+                const MachineOperand *&Target) const;
+
   const XtensaSubtarget &getSubtarget() const { return STI; }
 };
 } // end namespace llvm
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 9773480624e92e..e21de0448aa5ae 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -417,6 +417,8 @@ def BBSI : RRI8_Inst<0x07, (outs),
   let imm8 = target;
 }
 
+def : Pat<(brcond AR:$s, bb:$target), (BNEZ AR:$s, bb:$target)>;
+
 //===----------------------------------------------------------------------===//
 // Call and jump instructions
 //===----------------------------------------------------------------------===//
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..0e60a3307e7c43 100644
--- a/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp
@@ -95,6 +95,7 @@ class XtensaPassConfig : public TargetPassConfig {
   }
 
   bool addInstSelector() override;
+  void addPreEmitPass() override;
 };
 } // end anonymous namespace
 
@@ -103,6 +104,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/test/CodeGen/Xtensa/branch-relaxation.ll b/llvm/test/CodeGen/Xtensa/branch-relaxation.ll
new file mode 100644
index 00000000000000..78470e4d3a6fbc
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/branch-relaxation.ll
@@ -0,0 +1,42 @@
+; 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 @jx(i1 %a) {
+; XTENSA-LABEL: jx:
+; XTENSA:         movi a8, 1
+; XTENSA-NEXT:    and a8, a2, a8
+; XTENSA-NEXT:    bnez a8, .LBB0_1
+; XTENSA-NEXT:  # %bb.3:
+; XTENSA-NEXT:    l32r a8, .LCPI0_0
+; XTENSA-NEXT:    jx a8
+; XTENSA-NEXT:  .LBB0_1: # %iftrue
+; XTENSA-NEXT:    #APP
+; XTENSA-NEXT:    #NO_APP
+; XTENSA-NEXT:    #APP
+; XTENSA-NEXT:    .space 1048576
+; 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 1048576", ""()
+  br label %tail
+
+tail:
+  ret i32 1
+}
diff --git a/llvm/test/CodeGen/Xtensa/branch.ll b/llvm/test/CodeGen/Xtensa/branch.ll
new file mode 100644
index 00000000000000..a1f83478f4adb8
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/branch.ll
@@ -0,0 +1,139 @@
+; 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 void @foo(i32 %a, ptr %b, i1 %c) nounwind {
+; XTENSA-LABEL: foo:
+; XTENSA:         memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    beq a8, a2, .LBB0_14
+; XTENSA-NEXT:  # %bb.1: # %test2
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    bne a8, a2, .LBB0_14
+; XTENSA-NEXT:  # %bb.2: # %test3
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    blt a8, a2, .LBB0_14
+; XTENSA-NEXT:  # %bb.3: # %test4
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    bge a8, a2, .LBB0_14
+; XTENSA-NEXT:  # %bb.4: # %test5
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    bltu a8, a2, .LBB0_14
+; XTENSA-NEXT:  # %bb.5: # %test6
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    bgeu a8, a2, .LBB0_14
+; XTENSA-NEXT:  # %bb.6: # %test7
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    blt a2, a8, .LBB0_14
+; XTENSA-NEXT:  # %bb.7: # %test8
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    bge a2, a8, .LBB0_14
+; XTENSA-NEXT:  # %bb.8: # %test9
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    bltu a2, a8, .LBB0_14
+; XTENSA-NEXT:  # %bb.9: # %test10
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    bgeu a2, a8, .LBB0_14
+; XTENSA-NEXT:  # %bb.10: # %test11
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    movi a8, 1
+; XTENSA-NEXT:    and a8, a4, a8
+; XTENSA-NEXT:    bnez a8, .LBB0_14
+; XTENSA-NEXT:  # %bb.11: # %test12
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    movi a9, -1
+; XTENSA-NEXT:    blt a9, a8, .LBB0_14
+; XTENSA-NEXT:  # %bb.12: # %test13
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:    blti a8, 1, .LBB0_14
+; XTENSA-NEXT:  # %bb.13: # %test14
+; XTENSA-NEXT:    memw
+; XTENSA-NEXT:    l32i a8, a3, 0
+; XTENSA-NEXT:  .LBB0_14: # %end
+; XTENSA-NEXT:    ret
+  %val1 = load volatile i32, ptr %b
+  %tst1 = icmp eq i32 %val1, %a
+  br i1 %tst1, label %end, label %test2
+
+test2:
+  %val2 = load volatile i32, ptr %b
+  %tst2 = icmp ne i32 %val2, %a
+  br i1 %tst2, label %end, label %test3
+
+test3:
+  %val3 = load volatile i32, ptr %b
+  %tst3 = icmp slt i32 %val3, %a
+  br i1 %tst3, label %end, label %test4
+
+test4:
+  %val4 = load volatile i32, ptr %b
+  %tst4 = icmp sge i32 %val4, %a
+  br i1 %tst4, label %end, label %test5
+
+test5:
+  %val5 = load volatile i32, ptr %b
+  %tst5 = icmp ult i32 %val5, %a
+  br i1 %tst5, label %end, label %test6
+
+test6:
+  %val6 = load volatile i32, ptr %b
+  %tst6 = icmp uge i32 %val6, %a
+  br i1 %tst6, label %end, label %test7
+
+
+test7:
+  %val7 = load volatile i32, ptr %b
+  %tst7 = icmp sgt i32 %val7, %a
+  br i1 %tst7, label %end, label %test8
+
+test8:
+  %val8 = load volatile i32, ptr %b
+  %tst8 = icmp sle i32 %val8, %a
+  br i1 %tst8, label %end, label %test9
+
+test9:
+  %val9 = load volatile i32, ptr %b
+  %tst9 = icmp ugt i32 %val9, %a
+  br i1 %tst9, label %end, label %test10
+
+test10:
+  %val10 = load volatile i32, ptr %b
+  %tst10 = icmp ule i32 %val10, %a
+  br i1 %tst10, label %end, label %test11
+
+
+test11:
+  %val11 = load volatile i32, ptr %b
+  br i1 %c, label %end, label %test12
+
+
+test12:
+  %val12 = load volatile i32, ptr %b
+  %tst12 = icmp sgt i32 %val12, -1
+  br i1 %tst12, label %end, label %test13
+
+
+test13:
+  %val13 = load volatile i32, ptr %b
+  %tst13 = icmp slt i32 %val13, 1
+  br i1 %tst13, label %end, label %test14
+
+test14:
+  %val14 = load volatile i32, ptr %b
+  br label %end
+
+end:
+  ret void
+}
diff --git a/llvm/test/CodeGen/Xtensa/brcc.ll b/llvm/test/CodeGen/Xtensa/brcc.ll
index 8bbc39c536c561..6d542f637cf659 100644
--- a/llvm/test/CodeGen/Xtensa/brcc.ll
+++ b/llvm/test/CodeGen/Xtensa/brcc.ll
@@ -1,16 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc -mtriple=xtensa -disable-block-placement -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s
 
 define i32 @brcc_sgt(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_sgt:
 ; CHECK:         bge a3, a2, .LBB0_2
-; CHECK-NEXT:    j .LBB0_1
-; CHECK-NEXT:  .LBB0_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB0_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB0_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB0_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp sgt i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -28,13 +27,11 @@ exit:
 define i32 @brcc_ugt(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_ugt:
 ; CHECK:         bgeu a3, a2, .LBB1_2
-; CHECK-NEXT:    j .LBB1_1
-; CHECK-NEXT:  .LBB1_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB1_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB1_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB1_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp ugt i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -52,13 +49,11 @@ exit:
 define i32 @brcc_sle(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_sle:
 ; CHECK:         blt a3, a2, .LBB2_2
-; CHECK-NEXT:    j .LBB2_1
-; CHECK-NEXT:  .LBB2_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB2_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB2_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB2_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp sle i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -76,13 +71,11 @@ exit:
 define i32 @brcc_ule(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_ule:
 ; CHECK:         bltu a3, a2, .LBB3_2
-; CHECK-NEXT:    j .LBB3_1
-; CHECK-NEXT:  .LBB3_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB3_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB3_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB3_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp ule i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -100,13 +93,11 @@ exit:
 define i32 @brcc_eq(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_eq:
 ; CHECK:         bne a2, a3, .LBB4_2
-; CHECK-NEXT:    j .LBB4_1
-; CHECK-NEXT:  .LBB4_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB4_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB4_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB4_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp eq i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -124,13 +115,11 @@ exit:
 define i32 @brcc_ne(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_ne:
 ; CHECK:         beq a2, a3, .LBB5_2
-; CHECK-NEXT:    j .LBB5_1
-; CHECK-NEXT:  .LBB5_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB5_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB5_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB5_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp ne i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -148,13 +137,11 @@ exit:
 define i32 @brcc_ge(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_ge:
 ; CHECK:         blt a2, a3, .LBB6_2
-; CHECK-NEXT:    j .LBB6_1
-; CHECK-NEXT:  .LBB6_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB6_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB6_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB6_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp sge i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -172,13 +159,11 @@ exit:
 define i32 @brcc_lt(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_lt:
 ; CHECK:         bge a2, a3, .LBB7_2
-; CHECK-NEXT:    j .LBB7_1
-; CHECK-NEXT:  .LBB7_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB7_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB7_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB7_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp slt i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -196,13 +181,11 @@ exit:
 define i32 @brcc_uge(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_uge:
 ; CHECK:         bltu a2, a3, .LBB8_2
-; CHECK-NEXT:    j .LBB8_1
-; CHECK-NEXT:  .LBB8_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB8_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB8_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB8_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp uge i32 %a, %b
   br i1 %wb, label %t1, label %t2
@@ -220,13 +203,11 @@ exit:
 define i32 @brcc_ult(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: brcc_ult:
 ; CHECK:         bgeu a2, a3, .LBB9_2
-; CHECK-NEXT:    j .LBB9_1
-; CHECK-NEXT:  .LBB9_1: # %t1
+; CHECK-NEXT:  # %bb.1: # %t1
 ; CHECK-NEXT:    addi a2, a2, 4
-; CHECK-NEXT:    j .LBB9_3
+; CHECK-NEXT:    ret
 ; CHECK-NEXT:  .LBB9_2: # %t2
 ; CHECK-NEXT:    addi a2, a3, 8
-; CHECK-NEXT:  .LBB9_3: # %exit
 ; CHECK-NEXT:    ret
   %wb = icmp ult i32 %a, %b
   br i1 %wb, label %t1, label %t2
diff --git a/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
index f58bed19d4ee77..60303235386256 100644
--- a/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
+++ b/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
@@ -8,10 +8,8 @@ declare i32 @llvm.ctpop.i32(i32)
 
 define i32 @test_cttz_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_cttz_i32:
-; XTENSA:         movi a8, 32
-; XTENSA-NEXT:    beqz a2, .LBB0_2
-; XTENSA-NEXT:    j .LBB0_1
-; XTENSA-NEXT:  .LBB0_1: # %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,9 +31,10 @@ define i32 @test_cttz_i32(i32 %a) nounwind {
 ; XTENSA-NEXT:    add a8, a8, a9
 ; XTENSA-NEXT:    slli a9, a8, 16
 ; XTENSA-NEXT:    add a8, a8, a9
-; XTENSA-NEXT:    extui a8, a8, 24, 8
-; XTENSA-NEXT:  .LBB0_2: # %cond.end
-; XTENSA-NEXT:    or a2, a8, a8
+; XTENSA-NEXT:    extui a2, a8, 24, 8
+; XTENSA-NEXT:    ret
+; XTENSA-NEXT:  .LBB0_2:
+; XTENSA-NEXT:    movi a2, 32
 ; XTENSA-NEXT:    ret
   %tmp = call i32 @llvm.cttz.i32(i32 %a, i1 false)
   ret i32 %tmp
@@ -72,13 +71,10 @@ define i32 @test_cttz_i32_zero_undef(i32 %a) nounwind {
 
 define i32 @test_ctlz_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_ctlz_i32:
-; XTENSA:         or a8, a2, a2
-; XTENSA-NEXT:    movi a2, 32
-; XTENSA-NEXT:    beqz a8, .LBB2_2
-; XTENSA-NEXT:    j .LBB2_1
-; XTENSA-NEXT:  .LBB2_1: # %cond.false
-; XTENSA-NEXT:    srli a9, a8, 1
-; XTENSA-NEXT:    or a8, a8, a9
+; 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
 ; XTENSA-NEXT:    or a8, a8, a9
 ; XTENSA-NEXT:    srli a9, a8, 4
@@ -107,7 +103,9 @@ define i32 @test_ctlz_i32(i32 %a) nounwind {
 ; XTENSA-NEXT:    slli a9, a8, 16
 ; XTENSA-NEXT:    add a8, a8, a9
 ; XTENSA-NEXT:    extui a2, a8, 24, 8
-; XTENSA-NEXT:  .LBB2_2: # %cond.end
+; XTENSA-NEXT:    ret
+; XTENSA-NEXT:  .LBB2_2:
+; XTENSA-NEXT:    movi a2, 32
 ; XTENSA-NEXT:    ret
   %tmp = call i32 @llvm.ctlz.i32(i32 %a, i1 false)
   ret i32 %tmp
diff --git a/llvm/test/CodeGen/Xtensa/select-cc.ll b/llvm/test/CodeGen/Xtensa/select-cc.ll
index 812e6a5b852eab..c86aa9f33ca36b 100644
--- a/llvm/test/CodeGen/Xtensa/select-cc.ll
+++ b/llvm/test/CodeGen/Xtensa/select-cc.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc -mtriple=xtensa -disable-block-placement -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s
 
@@ -161,12 +162,10 @@ define i32 @f_slt_imm(i32 %a, ptr %b) nounwind {
 
 define i32 @f_sgt_imm(i32 %a, ptr %b) nounwind {
 ; CHECK-LABEL: f_sgt_imm:
-; CHECK:         or a8, a2, a2
-; CHECK-NEXT:    l32i a2, a3, 0
-; CHECK-NEXT:    movi a9, -1
-; CHECK-NEXT:    bge a9, a8, .LBB11_2
+; CHECK:         movi a8, -1
+; CHECK-NEXT:    blt a8, a2, .LBB11_2
 ; CHECK-NEXT:  # %bb.1:
-; CHECK-NEXT:    or a2, a8, a8
+; CHECK-NEXT:    l32i a2, a3, 0
 ; CHECK-NEXT:  .LBB11_2:
 ; CHECK-NEXT:    ret
   %val1 = load i32, ptr %b

>From 51518b90b015f8b2da3ceed9f156e3366a7e6188 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Fri, 11 Oct 2024 02:48:48 +0300
Subject: [PATCH 2/2] [PATCH] [Xtensa] Remove redundant code.

---
 llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp   |   3 -
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp    | 180 ------------------
 llvm/lib/Target/Xtensa/XtensaInstrInfo.h      |  17 --
 llvm/lib/Target/Xtensa/XtensaRegisterInfo.h   |   4 -
 .../lib/Target/Xtensa/XtensaTargetMachine.cpp |   3 -
 llvm/test/CodeGen/Xtensa/branch-relaxation.ll |  42 ----
 llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll   |  12 +-
 7 files changed, 6 insertions(+), 255 deletions(-)
 delete 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 95dfafc13f3908..db86637ecf83f3 100644
--- a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
@@ -69,9 +69,6 @@ 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/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index c944ea52533fcb..f7cfcbd03f229f 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -13,13 +13,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "XtensaInstrInfo.h"
-#include "XtensaConstantPoolValue.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"
@@ -188,18 +186,6 @@ 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!");
@@ -261,77 +247,6 @@ 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,
@@ -464,101 +379,6 @@ 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();
-
-  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));
-
-  // FIXME: A virtual register must be used initially, as the register
-  // scavenger won't work with empty blocks (SIInstrInfo::insertIndirectBranch
-  // uses the same workaround).
-  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);
-  unsigned Scav = RS->scavengeRegisterBackwards(Xtensa::ARRegClass,
-                                                L32R.getIterator(), false, 0);
-  MRI.replaceRegWith(ScratchReg, Scav);
-  MRI.clearVirtRegs();
-  RS->setRegUsed(Scav);
-}
-
-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 ce9484a89751dd..6e00f49a95c823 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
@@ -38,8 +38,6 @@ 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; }
 
@@ -79,11 +77,6 @@ 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,
@@ -97,22 +90,12 @@ 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/XtensaRegisterInfo.h b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
index ede0eeb90b42de..8643ebb1c0f157 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.h
@@ -38,10 +38,6 @@ 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 0e60a3307e7c43..49c7faf84df1d3 100644
--- a/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp
@@ -95,7 +95,6 @@ class XtensaPassConfig : public TargetPassConfig {
   }
 
   bool addInstSelector() override;
-  void addPreEmitPass() override;
 };
 } // end anonymous namespace
 
@@ -104,8 +103,6 @@ bool XtensaPassConfig::addInstSelector() {
   return false;
 }
 
-void XtensaPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
-
 TargetPassConfig *XtensaTargetMachine::createPassConfig(PassManagerBase &PM) {
   return new XtensaPassConfig(*this, PM);
 }
diff --git a/llvm/test/CodeGen/Xtensa/branch-relaxation.ll b/llvm/test/CodeGen/Xtensa/branch-relaxation.ll
deleted file mode 100644
index 78470e4d3a6fbc..00000000000000
--- a/llvm/test/CodeGen/Xtensa/branch-relaxation.ll
+++ /dev/null
@@ -1,42 +0,0 @@
-; 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 @jx(i1 %a) {
-; XTENSA-LABEL: jx:
-; XTENSA:         movi a8, 1
-; XTENSA-NEXT:    and a8, a2, a8
-; XTENSA-NEXT:    bnez a8, .LBB0_1
-; XTENSA-NEXT:  # %bb.3:
-; XTENSA-NEXT:    l32r a8, .LCPI0_0
-; XTENSA-NEXT:    jx a8
-; XTENSA-NEXT:  .LBB0_1: # %iftrue
-; XTENSA-NEXT:    #APP
-; XTENSA-NEXT:    #NO_APP
-; XTENSA-NEXT:    #APP
-; XTENSA-NEXT:    .space 1048576
-; 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 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 60303235386256..bad57d58b28a67 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_2
-; XTENSA-NEXT:  # %bb.1: # %cond.false
+; XTENSA:         beqz a2, .LBB0_1
+; XTENSA-NEXT:  # %bb.2: # %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_2:
+; XTENSA-NEXT:  .LBB0_1:
 ; 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_2
-; XTENSA-NEXT:  # %bb.1: # %cond.false
+; XTENSA:         beqz a2, .LBB2_1
+; XTENSA-NEXT:  # %bb.2: # %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_2:
+; XTENSA-NEXT:  .LBB2_1:
 ; XTENSA-NEXT:    movi a2, 32
 ; XTENSA-NEXT:    ret
   %tmp = call i32 @llvm.ctlz.i32(i32 %a, i1 false)



More information about the llvm-commits mailing list