From 2b1a8b11349bc1ff82bcc61a987fe81cd0278f3c Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Thu, 3 Oct 2024 09:14:38 +0300 Subject: [PATCH 1/3] [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 db86637ecf83f..95dfafc13f390 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(ACPV)->getBlockAddress(); MCSym = GetBlockAddressSymbol(BA); + } else if (ACPV->isMachineBasicBlock()) { + const MachineBasicBlock *MBB = cast(ACPV)->getMBB(); + MCSym = MBB->getSymbol(); } else if (ACPV->isJumpTable()) { unsigned Idx = cast(ACPV)->getIndex(); MCSym = this->GetJTISymbol(Idx, false); diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp index 2263aadcb0dd3..c944ea52533fc 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 &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 &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 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 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 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 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 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 &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 8bf3f0618f285..ce9484a89751d 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 &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 &Cond, + bool AllowModify) const override; + + unsigned removeBranch(MachineBasicBlock &MBB, + int *BytesRemoved = nullptr) const override; + + unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, ArrayRef 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 Cond, const DebugLoc &DL, + int *BytesAdded) const; + + unsigned InsertConstBranchAtInst(MachineBasicBlock &MBB, MachineInstr *I, + int64_t offset, + ArrayRef 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 &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 9773480624e92..e21de0448aa5a 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 8643ebb1c0f15..ede0eeb90b42d 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 49c7faf84df1d..0e60a3307e7c4 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 0000000000000..78470e4d3a6fb --- /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 0000000000000..a1f83478f4adb --- /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 8bbc39c536c56..6d542f637cf65 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 f58bed19d4ee7..6030323538625 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 812e6a5b852ea..c86aa9f33ca36 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 Date: Fri, 11 Oct 2024 02:48:48 +0300 Subject: [PATCH 2/3] [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 95dfafc13f390..db86637ecf83f 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(ACPV)->getBlockAddress(); MCSym = GetBlockAddressSymbol(BA); - } else if (ACPV->isMachineBasicBlock()) { - const MachineBasicBlock *MBB = cast(ACPV)->getMBB(); - MCSym = MBB->getSymbol(); } else if (ACPV->isJumpTable()) { unsigned Idx = cast(ACPV)->getIndex(); MCSym = this->GetJTISymbol(Idx, false); diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp index c944ea52533fc..f7cfcbd03f229 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 &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 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 ce9484a89751d..6e00f49a95c82 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 &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 &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 Cond, const DebugLoc &DL, int *BytesAdded) const; - unsigned InsertConstBranchAtInst(MachineBasicBlock &MBB, MachineInstr *I, - int64_t offset, - ArrayRef 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 ede0eeb90b42d..8643ebb1c0f15 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 0e60a3307e7c4..49c7faf84df1d 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 78470e4d3a6fb..0000000000000 --- 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 6030323538625..bad57d58b28a6 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) From d2b7aabc089510f8ad8615bfb92e55764f5e14e7 Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Mon, 21 Oct 2024 20:20:17 +0300 Subject: [PATCH 3/3] [Xtensa] Fix tests and minor fixes in code. --- llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp | 9 +- llvm/lib/Target/Xtensa/XtensaInstrInfo.h | 2 +- llvm/test/CodeGen/Xtensa/branch.ll | 139 ---- llvm/test/CodeGen/Xtensa/branch_analyze.ll | 871 +++++++++++++++++++++ 4 files changed, 875 insertions(+), 146 deletions(-) delete mode 100644 llvm/test/CodeGen/Xtensa/branch.ll create mode 100644 llvm/test/CodeGen/Xtensa/branch_analyze.ll diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp index f7cfcbd03f229..b2b4376ca040b 100644 --- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp @@ -209,7 +209,6 @@ bool XtensaInstrInfo::reverseBranchCondition( case Xtensa::BGEU: Cond[0].setImm(Xtensa::BLTU); return false; - case Xtensa::BEQI: Cond[0].setImm(Xtensa::BNEI); return false; @@ -228,7 +227,6 @@ bool XtensaInstrInfo::reverseBranchCondition( case Xtensa::BLTUI: Cond[0].setImm(Xtensa::BGEUI); return false; - case Xtensa::BEQZ: Cond[0].setImm(Xtensa::BNEZ); return false; @@ -241,7 +239,6 @@ bool XtensaInstrInfo::reverseBranchCondition( case Xtensa::BGEZ: Cond[0].setImm(Xtensa::BLTZ); return false; - default: report_fatal_error("Invalid branch condition!"); } @@ -367,7 +364,7 @@ unsigned XtensaInstrInfo::insertBranch( // 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); + Count = insertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded); auto &MI = *BuildMI(&MBB, DL, get(Xtensa::J)).addMBB(FBB); Count++; if (BytesAdded) @@ -375,11 +372,11 @@ unsigned XtensaInstrInfo::insertBranch( return Count; } // This function inserts the branch at the end of the MBB - Count += InsertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded); + Count += insertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded); return Count; } -unsigned XtensaInstrInfo::InsertBranchAtInst(MachineBasicBlock &MBB, +unsigned XtensaInstrInfo::insertBranchAtInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *TBB, ArrayRef Cond, diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h index 6e00f49a95c82..9f45cf7c29ada 100644 --- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h @@ -90,7 +90,7 @@ class XtensaInstrInfo : public XtensaGenInstrInfo { const DebugLoc &DL, int *BytesAdded = nullptr) const override; - unsigned InsertBranchAtInst(MachineBasicBlock &MBB, + unsigned insertBranchAtInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *TBB, ArrayRef Cond, const DebugLoc &DL, diff --git a/llvm/test/CodeGen/Xtensa/branch.ll b/llvm/test/CodeGen/Xtensa/branch.ll deleted file mode 100644 index a1f83478f4adb..0000000000000 --- a/llvm/test/CodeGen/Xtensa/branch.ll +++ /dev/null @@ -1,139 +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 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/branch_analyze.ll b/llvm/test/CodeGen/Xtensa/branch_analyze.ll new file mode 100644 index 0000000000000..3c0bcc5452182 --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/branch_analyze.ll @@ -0,0 +1,871 @@ +; 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 + +declare void @foo() noreturn + +; Check reverseBranchCondition and analyzeBranch functions + +define i32 @eq(i32 %a, ptr %bptr) { +; XTENSA-LABEL: eq: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: beq a2, a8, .LBB0_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB0_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI0_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp eq i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @eq_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: eq_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bne a2, a8, .LBB1_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB1_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI1_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp eq i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ne(i32 %a, ptr %bptr) { +; XTENSA-LABEL: ne: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bne a2, a8, .LBB2_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB2_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI2_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp ne i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ne_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: ne_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: beq a2, a8, .LBB3_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB3_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI3_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp ne i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ult(i32 %a, ptr %bptr) { +; XTENSA-LABEL: ult: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bltu a2, a8, .LBB4_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB4_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI4_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp ult i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ult_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: ult_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bgeu a2, a8, .LBB5_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB5_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI5_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp ult i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @uge(i32 %a, ptr %bptr) { +; XTENSA-LABEL: uge: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bgeu a2, a8, .LBB6_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB6_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI6_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp uge i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @uge_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: uge_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bltu a2, a8, .LBB7_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB7_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI7_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp uge i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @slt(i32 %a, ptr %bptr) { +; XTENSA-LABEL: slt: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: blt a2, a8, .LBB8_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB8_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI8_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp slt i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @slt_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: slt_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bge a2, a8, .LBB9_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB9_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI9_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp slt i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @sle(i32 %a, ptr %bptr) { +; XTENSA-LABEL: sle: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bge a8, a2, .LBB10_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB10_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI10_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp sle i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @sle_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: sle_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: blt a8, a2, .LBB11_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB11_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI11_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp sle i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @sgt(i32 %a, ptr %bptr) { +; XTENSA-LABEL: sgt: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: blt a8, a2, .LBB12_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB12_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI12_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp sgt i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @sgt_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: sgt_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bge a8, a2, .LBB13_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB13_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI13_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp sgt i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @sge(i32 %a, ptr %bptr) { +; XTENSA-LABEL: sge: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: bge a2, a8, .LBB14_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB14_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI14_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp sge i32 %a, %b + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @sge_reverse(i32 %a, ptr %bptr) { +; XTENSA-LABEL: sge_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: l32i a8, a3, 0 +; XTENSA-NEXT: blt a2, a8, .LBB15_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB15_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI15_0 +; XTENSA-NEXT: callx0 a8 +entry: + %b = load i32, ptr %bptr + %cmp = icmp sge i32 %a, %b + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +; Check some cases of comparing operand with constant. + +define i32 @eq_zero(ptr %aptr) { +; XTENSA-LABEL: eq_zero: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: memw +; XTENSA-NEXT: l32i a8, a2, 0 +; XTENSA-NEXT: beqz a8, .LBB16_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB16_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI16_0 +; XTENSA-NEXT: callx0 a8 +entry: + %a = load volatile i32, ptr %aptr + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @eq_zero_reverse(ptr %aptr) { +; XTENSA-LABEL: eq_zero_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: memw +; XTENSA-NEXT: l32i a8, a2, 0 +; XTENSA-NEXT: bnez a8, .LBB17_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB17_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI17_0 +; XTENSA-NEXT: callx0 a8 +entry: + %a = load volatile i32, ptr %aptr + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ne_zero(ptr %aptr) { +; XTENSA-LABEL: ne_zero: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: memw +; XTENSA-NEXT: l32i a8, a2, 0 +; XTENSA-NEXT: bnez a8, .LBB18_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB18_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI18_0 +; XTENSA-NEXT: callx0 a8 +entry: + %a = load volatile i32, ptr %aptr + %cmp = icmp ne i32 %a, 0 + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ne_zero_reverse(ptr %aptr) { +; XTENSA-LABEL: ne_zero_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: memw +; XTENSA-NEXT: l32i a8, a2, 0 +; XTENSA-NEXT: beqz a8, .LBB19_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB19_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI19_0 +; XTENSA-NEXT: callx0 a8 +entry: + %a = load volatile i32, ptr %aptr + %cmp = icmp ne i32 %a, 0 + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @slt_zero(ptr %aptr) { +; XTENSA-LABEL: slt_zero: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: memw +; XTENSA-NEXT: l32i a8, a2, 0 +; XTENSA-NEXT: bgez a8, .LBB20_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB20_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI20_0 +; XTENSA-NEXT: callx0 a8 +entry: + %a = load volatile i32, ptr %aptr + %cmp = icmp slt i32 %a, 0 + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @eq_imm(i32 %a) { +; XTENSA-LABEL: eq_imm: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: beqi a2, 1, .LBB21_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB21_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI21_0 +; XTENSA-NEXT: callx0 a8 +entry: + %cmp = icmp eq i32 %a, 1 + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @eq_imm_reverse(i32 %a) { +; XTENSA-LABEL: eq_imm_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: bnei a2, 1, .LBB22_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB22_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI22_0 +; XTENSA-NEXT: callx0 a8 +entry: + %cmp = icmp eq i32 %a, 1 + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ne_imm(i32 %a) { +; XTENSA-LABEL: ne_imm: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: beqi a2, 1, .LBB23_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB23_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI23_0 +; XTENSA-NEXT: callx0 a8 +entry: + %cmp = icmp eq i32 %a, 1 + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @ne_imm_reverse(i32 %a) { +; XTENSA-LABEL: ne_imm_reverse: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: bnei a2, 1, .LBB24_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB24_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI24_0 +; XTENSA-NEXT: callx0 a8 +entry: + %cmp = icmp eq i32 %a, 1 + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @slt_imm(i32 %a) { +; XTENSA-LABEL: slt_imm: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: bgei a2, -1, .LBB25_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB25_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI25_0 +; XTENSA-NEXT: callx0 a8 +entry: + %cmp = icmp slt i32 %a, -1 + br i1 %cmp, label %return, label %callit + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @sge_imm(i32 %a) { +; XTENSA-LABEL: sge_imm: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: beqz a2, .LBB26_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB26_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI26_0 +; XTENSA-NEXT: callx0 a8 +entry: + %cmp = icmp ult i32 %a, 1 + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +} + +define i32 @uge_imm(ptr %aptr) { +; XTENSA-LABEL: uge_imm: +; XTENSA: addi a8, a1, -16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: .cfi_def_cfa_offset 16 +; XTENSA-NEXT: s32i a0, a1, 0 # 4-byte Folded Spill +; XTENSA-NEXT: .cfi_offset a0, -4 +; XTENSA-NEXT: memw +; XTENSA-NEXT: l32i a8, a2, 0 +; XTENSA-NEXT: bgeui a8, 2, .LBB27_2 +; XTENSA-NEXT: # %bb.1: # %return +; XTENSA-NEXT: movi a2, 1 +; XTENSA-NEXT: l32i a0, a1, 0 # 4-byte Folded Reload +; XTENSA-NEXT: addi a8, a1, 16 +; XTENSA-NEXT: or a1, a8, a8 +; XTENSA-NEXT: ret +; XTENSA-NEXT: .LBB27_2: # %callit +; XTENSA-NEXT: l32r a8, .LCPI27_0 +; XTENSA-NEXT: callx0 a8 +entry: + %a = load volatile i32, ptr %aptr + %cmp = icmp uge i32 %a, 2 + br i1 %cmp, label %callit, label %return + +callit: + call void @foo() + unreachable + +return: + ret i32 1 +}