https://github.com/heiher created https://github.com/llvm/llvm-project/pull/216261
The patch adds a late optimization pass that replaces conditional branches that can be statically evaluated with an unconditinal branch. This pass is inspired by RISC-V's RISCVLateBranchOpt pass. >From 08d3ff7cacea5f4f12dc49001f81e04c66666e37 Mon Sep 17 00:00:00 2001 From: WANG Rui <[email protected]> Date: Thu, 13 Aug 2026 17:57:27 +0800 Subject: [PATCH] [LoongArch] Add late branch optimization pass The patch adds a late optimization pass that replaces conditional branches that can be statically evaluated with an unconditinal branch. This pass is inspired by RISC-V's RISCVLateBranchOpt pass. --- llvm/lib/Target/LoongArch/CMakeLists.txt | 1 + llvm/lib/Target/LoongArch/LoongArch.h | 2 + .../LoongArch/LoongArchISelLowering.cpp | 14 + .../LoongArch/LoongArchLateBranchOpt.cpp | 122 ++++++ .../LoongArch/LoongArchTargetMachine.cpp | 8 + llvm/test/CodeGen/LoongArch/branch-opt.ll | 351 +++--------------- llvm/test/CodeGen/LoongArch/jr-without-ra.ll | 90 ++--- llvm/test/CodeGen/LoongArch/opt-pipeline.ll | 4 + llvm/test/CodeGen/LoongArch/pr215935.ll | 10 - ...arch_generated_funcs.ll.generated.expected | 20 +- ...ch_generated_funcs.ll.nogenerated.expected | 20 +- .../llvm/lib/Target/LoongArch/BUILD.gn | 1 + 12 files changed, 241 insertions(+), 402 deletions(-) create mode 100644 llvm/lib/Target/LoongArch/LoongArchLateBranchOpt.cpp diff --git a/llvm/lib/Target/LoongArch/CMakeLists.txt b/llvm/lib/Target/LoongArch/CMakeLists.txt index c856173ca89de..084544ff4112d 100644 --- a/llvm/lib/Target/LoongArch/CMakeLists.txt +++ b/llvm/lib/Target/LoongArch/CMakeLists.txt @@ -24,6 +24,7 @@ add_llvm_target(LoongArchCodeGen LoongArchInstrInfo.cpp LoongArchISelDAGToDAG.cpp LoongArchISelLowering.cpp + LoongArchLateBranchOpt.cpp LoongArchMCInstLower.cpp LoongArchMergeBaseOffset.cpp LoongArchOptWInstrs.cpp diff --git a/llvm/lib/Target/LoongArch/LoongArch.h b/llvm/lib/Target/LoongArch/LoongArch.h index e5b3083348792..6762f91df72d9 100644 --- a/llvm/lib/Target/LoongArch/LoongArch.h +++ b/llvm/lib/Target/LoongArch/LoongArch.h @@ -41,6 +41,7 @@ FunctionPass *createLoongArchMergeBaseOffsetOptPass(); FunctionPass *createLoongArchOptWInstrsPass(); FunctionPass *createLoongArchPreRAExpandPseudoPass(); FunctionPass *createLoongArchExpandPseudoPass(); +FunctionPass *createLoongArchLateBranchOptPass(); void initializeLoongArchAsmPrinterPass(PassRegistry &); void initializeLoongArchDAGToDAGISelLegacyPass(PassRegistry &); void initializeLoongArchDeadRegisterDefinitionsPass(PassRegistry &); @@ -49,6 +50,7 @@ void initializeLoongArchMergeBaseOffsetOptPass(PassRegistry &); void initializeLoongArchOptWInstrsPass(PassRegistry &); void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &); void initializeLoongArchExpandPseudoPass(PassRegistry &); +void initializeLoongArchLateBranchOptPass(PassRegistry &); } // end namespace llvm #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 92e1feb07ae50..55f779a612909 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -7314,6 +7314,20 @@ static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, } } + // Fold (C1, C2, cond) -> (0, 0, seteq/setne) + if (isa<ConstantSDNode>(LHS) && isa<ConstantSDNode>(RHS)) { + const LoongArchTargetLowering *TLI = Subtarget.getTargetLowering(); + EVT VT = LHS.getValueType(); + EVT SetCCResVT = + TLI->getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT); + if (SDValue Folded = DAG.FoldSetCC(SetCCResVT, LHS, RHS, CCVal, DL)) { + LHS = DAG.getConstant(0, DL, VT); + RHS = DAG.getConstant(0, DL, VT); + CC = DAG.getCondCode(!isNullConstant(Folded) ? ISD::SETEQ : ISD::SETNE); + return true; + } + } + return false; } diff --git a/llvm/lib/Target/LoongArch/LoongArchLateBranchOpt.cpp b/llvm/lib/Target/LoongArch/LoongArchLateBranchOpt.cpp new file mode 100644 index 0000000000000..988b0427cfae2 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchLateBranchOpt.cpp @@ -0,0 +1,122 @@ +//===-- LoongArchLateBranchOpt.cpp - Late Stage Branch Optimization +//-----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// This file provides LoongArch specific target optimizations, currently it's +/// limited to convert conditional branches into unconditional branches when +/// the condition can be statically evaluated. +/// +//===----------------------------------------------------------------------===// + +#include "LoongArchInstrInfo.h" +#include "LoongArchSubtarget.h" + +using namespace llvm; + +#define LOONGARCH_LATE_BRANCH_OPT_NAME "LoongArch Late Branch Optimisation Pass" + +namespace { + +struct LoongArchLateBranchOpt : public MachineFunctionPass { + static char ID; + + LoongArchLateBranchOpt() : MachineFunctionPass(ID) {} + + StringRef getPassName() const override { + return LOONGARCH_LATE_BRANCH_OPT_NAME; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &Fn) override; + +private: + bool runOnBasicBlock(MachineBasicBlock &MBB) const; + + const LoongArchInstrInfo *TII = nullptr; +}; +} // namespace + +char LoongArchLateBranchOpt::ID = 0; +INITIALIZE_PASS(LoongArchLateBranchOpt, "loongarch-late-branch-opt", + LOONGARCH_LATE_BRANCH_OPT_NAME, false, false) + +bool LoongArchLateBranchOpt::runOnBasicBlock(MachineBasicBlock &MBB) const { + MachineBasicBlock *TBB, *FBB; + SmallVector<MachineOperand, 4> Cond; + if (TII->analyzeBranch(MBB, TBB, FBB, Cond, /*AllowModify=*/false)) + return false; + + if (!TBB || Cond.size() < 1) + return false; + + // Try and convert a conditional branch that can be evaluated statically + // into an unconditional branch. + unsigned Opc = Cond[0].getImm(); + MachineBasicBlock *Folded; + switch (Opc) { + case LoongArch::BEQZ: + case LoongArch::BNEZ: + if (Cond.size() < 2 || !Cond[1].isReg() || + Cond[1].getReg() != LoongArch::R0) + return false; + Folded = (Opc == LoongArch::BEQZ) ? TBB : FBB; + break; + case LoongArch::BEQ: + case LoongArch::BNE: + if (Cond.size() < 3 || !Cond[1].isReg() || !Cond[2].isReg() || + Cond[1].getReg() != Cond[2].getReg()) + return false; + Folded = (Opc == LoongArch::BEQ) ? TBB : FBB; + break; + default: + return false; + } + + // At this point, its legal to optimize. + TII->removeBranch(MBB); + + // Only need to insert a branch if we're not falling through. + if (Folded) { + DebugLoc DL = MBB.findBranchDebugLoc(); + TII->insertBranch(MBB, Folded, nullptr, {}, DL); + } + + // Update the successors. Remove them all and add back the correct one. + while (!MBB.succ_empty()) + MBB.removeSuccessor(MBB.succ_end() - 1); + + // If it's a fallthrough, we need to figure out where MBB is going. + if (!Folded) { + MachineFunction::iterator Fallthrough = ++MBB.getIterator(); + if (Fallthrough != MBB.getParent()->end()) + MBB.addSuccessor(&*Fallthrough); + } else + MBB.addSuccessor(Folded); + + return true; +} + +bool LoongArchLateBranchOpt::runOnMachineFunction(MachineFunction &Fn) { + if (skipFunction(Fn.getFunction())) + return false; + + auto &ST = Fn.getSubtarget<LoongArchSubtarget>(); + TII = ST.getInstrInfo(); + + bool Changed = false; + for (MachineBasicBlock &MBB : Fn) + Changed |= runOnBasicBlock(MBB); + return Changed; +} + +FunctionPass *llvm::createLoongArchLateBranchOptPass() { + return new LoongArchLateBranchOpt(); +} diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp index fb0053b7077e4..027650f92a08a 100644 --- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp @@ -44,6 +44,7 @@ LLVMInitializeLoongArchTarget() { initializeLoongArchExpandPseudoPass(*PR); initializeLoongArchDAGToDAGISelLegacyPass(*PR); initializeLoongArchExpandAtomicPseudoPass(*PR); + initializeLoongArchLateBranchOptPass(*PR); } static cl::opt<bool> EnableLoongArchDeadRegisterElimination( @@ -165,6 +166,7 @@ class LoongArchPassConfig : public TargetPassConfig { void addPreRegAlloc() override; bool addRegAssignAndRewriteFast() override; bool addRegAssignAndRewriteOptimized() override; + void addMachineLateOptimization() override; }; } // end namespace @@ -239,3 +241,9 @@ bool LoongArchPassConfig::addRegAssignAndRewriteOptimized() { addPass(createLoongArchDeadRegisterDefinitionsPass()); return TargetPassConfig::addRegAssignAndRewriteOptimized(); } + +void LoongArchPassConfig::addMachineLateOptimization() { + if (TM->getOptLevel() != CodeGenOptLevel::None) + addPass(createLoongArchLateBranchOptPass()); + TargetPassConfig::addMachineLateOptimization(); +} diff --git a/llvm/test/CodeGen/LoongArch/branch-opt.ll b/llvm/test/CodeGen/LoongArch/branch-opt.ll index 2a7712afb44af..fa4b558a58d55 100644 --- a/llvm/test/CodeGen/LoongArch/branch-opt.ll +++ b/llvm/test/CodeGen/LoongArch/branch-opt.ll @@ -1,38 +1,13 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch32 -mattr=-32s,+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32R -; RUN: llc --mtriple=loongarch32 -mattr=+32s,+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA32S -; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s --check-prefix=LA64 +; RUN: llc --mtriple=loongarch32 -mattr=-32s,+d --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch32 -mattr=+32s,+d --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 -mattr=+d --verify-machineinstrs < %s | FileCheck %s define i32 @br_eq() nounwind { -; LA32R-LABEL: br_eq: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: beq $zero, $zero, .LBB0_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB0_2: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_eq: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: beqz $zero, .LBB0_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB0_2: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; -; LA64-LABEL: br_eq: -; LA64: # %bb.0: # %entry -; LA64-NEXT: beqz $zero, .LBB0_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret -; LA64-NEXT: .LBB0_2: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret +; CHECK-LABEL: br_eq: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: move $a0, $zero +; CHECK-NEXT: ret entry: %1 = icmp eq i32 0, 0 br i1 %1, label %2, label %3 @@ -43,38 +18,10 @@ entry: } define i32 @br_ne() nounwind { -; LA32R-LABEL: br_ne: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: beq $a0, $zero, .LBB1_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB1_2: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_ne: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: beqz $a0, .LBB1_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB1_2: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; -; LA64-LABEL: br_ne: -; LA64: # %bb.0: # %entry -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: beqz $a0, .LBB1_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret -; LA64-NEXT: .LBB1_2: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret +; CHECK-LABEL: br_ne: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ori $a0, $zero, 1 +; CHECK-NEXT: ret entry: %1 = icmp ne i32 0, 1 br i1 %1, label %3, label %2 @@ -85,35 +32,10 @@ entry: } define i32 @br_lt() nounwind { -; LA32R-LABEL: br_lt: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: beq $zero, $zero, .LBB2_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB2_2: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_lt: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: beqz $zero, .LBB2_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB2_2: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; -; LA64-LABEL: br_lt: -; LA64: # %bb.0: # %entry -; LA64-NEXT: beqz $zero, .LBB2_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret -; LA64-NEXT: .LBB2_2: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret +; CHECK-LABEL: br_lt: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: move $a0, $zero +; CHECK-NEXT: ret entry: %1 = icmp slt i32 0, 1 br i1 %1, label %2, label %3 @@ -124,35 +46,10 @@ entry: } define i32 @br_le() nounwind { -; LA32R-LABEL: br_le: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: bne $zero, $zero, .LBB3_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB3_2: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_le: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: bnez $zero, .LBB3_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB3_2: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; -; LA64-LABEL: br_le: -; LA64: # %bb.0: # %entry -; LA64-NEXT: bnez $zero, .LBB3_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret -; LA64-NEXT: .LBB3_2: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret +; CHECK-LABEL: br_le: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: move $a0, $zero +; CHECK-NEXT: ret entry: %1 = icmp sle i32 0, 1 br i1 %1, label %2, label %3 @@ -163,38 +60,10 @@ entry: } define i32 @br_gt() nounwind { -; LA32R-LABEL: br_gt: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: beq $a0, $zero, .LBB4_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB4_2: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_gt: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: beqz $a0, .LBB4_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB4_2: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; -; LA64-LABEL: br_gt: -; LA64: # %bb.0: # %entry -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: beqz $a0, .LBB4_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret -; LA64-NEXT: .LBB4_2: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret +; CHECK-LABEL: br_gt: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ori $a0, $zero, 1 +; CHECK-NEXT: ret entry: %1 = icmp sgt i32 1, 0 br i1 %1, label %3, label %2 @@ -205,38 +74,10 @@ entry: } define i32 @br_ge() nounwind { -; LA32R-LABEL: br_ge: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: beq $a0, $zero, .LBB5_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB5_2: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_ge: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: beqz $a0, .LBB5_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB5_2: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; -; LA64-LABEL: br_ge: -; LA64: # %bb.0: # %entry -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: beqz $a0, .LBB5_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret -; LA64-NEXT: .LBB5_2: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret +; CHECK-LABEL: br_ge: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ori $a0, $zero, 1 +; CHECK-NEXT: ret entry: %1 = icmp sge i32 1, 0 br i1 %1, label %3, label %2 @@ -247,35 +88,10 @@ entry: } define i32 @br_ltu() nounwind { -; LA32R-LABEL: br_ltu: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: bne $zero, $zero, .LBB6_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB6_2: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_ltu: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: bnez $zero, .LBB6_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB6_2: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; -; LA64-LABEL: br_ltu: -; LA64: # %bb.0: # %entry -; LA64-NEXT: bnez $zero, .LBB6_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret -; LA64-NEXT: .LBB6_2: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret +; CHECK-LABEL: br_ltu: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: move $a0, $zero +; CHECK-NEXT: ret entry: %1 = icmp ult i32 0, 1 br i1 %1, label %2, label %3 @@ -286,35 +102,10 @@ entry: } define i32 @br_leu() nounwind { -; LA32R-LABEL: br_leu: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: bne $zero, $zero, .LBB7_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB7_2: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_leu: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: bnez $zero, .LBB7_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB7_2: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; -; LA64-LABEL: br_leu: -; LA64: # %bb.0: # %entry -; LA64-NEXT: bnez $zero, .LBB7_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret -; LA64-NEXT: .LBB7_2: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret +; CHECK-LABEL: br_leu: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: move $a0, $zero +; CHECK-NEXT: ret entry: %1 = icmp ule i32 0, 1 br i1 %1, label %2, label %3 @@ -325,38 +116,10 @@ entry: } define i32 @br_gtu() nounwind { -; LA32R-LABEL: br_gtu: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: beq $a0, $zero, .LBB8_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB8_2: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_gtu: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: beqz $a0, .LBB8_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB8_2: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; -; LA64-LABEL: br_gtu: -; LA64: # %bb.0: # %entry -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: beqz $a0, .LBB8_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret -; LA64-NEXT: .LBB8_2: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret +; CHECK-LABEL: br_gtu: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ori $a0, $zero, 1 +; CHECK-NEXT: ret entry: %1 = icmp ugt i32 1, 0 br i1 %1, label %3, label %2 @@ -366,38 +129,10 @@ entry: ret i32 1 } define i32 @br_geu() nounwind { -; LA32R-LABEL: br_geu: -; LA32R: # %bb.0: # %entry -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: beq $a0, $zero, .LBB9_2 -; LA32R-NEXT: # %bb.1: -; LA32R-NEXT: ori $a0, $zero, 1 -; LA32R-NEXT: ret -; LA32R-NEXT: .LBB9_2: -; LA32R-NEXT: move $a0, $zero -; LA32R-NEXT: ret -; -; LA32S-LABEL: br_geu: -; LA32S: # %bb.0: # %entry -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: beqz $a0, .LBB9_2 -; LA32S-NEXT: # %bb.1: -; LA32S-NEXT: ori $a0, $zero, 1 -; LA32S-NEXT: ret -; LA32S-NEXT: .LBB9_2: -; LA32S-NEXT: move $a0, $zero -; LA32S-NEXT: ret -; -; LA64-LABEL: br_geu: -; LA64: # %bb.0: # %entry -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: beqz $a0, .LBB9_2 -; LA64-NEXT: # %bb.1: -; LA64-NEXT: ori $a0, $zero, 1 -; LA64-NEXT: ret -; LA64-NEXT: .LBB9_2: -; LA64-NEXT: move $a0, $zero -; LA64-NEXT: ret +; CHECK-LABEL: br_geu: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ori $a0, $zero, 1 +; CHECK-NEXT: ret entry: %1 = icmp uge i32 1, 0 br i1 %1, label %3, label %2 diff --git a/llvm/test/CodeGen/LoongArch/jr-without-ra.ll b/llvm/test/CodeGen/LoongArch/jr-without-ra.ll index 96c9e7523f642..814e2f2c70287 100644 --- a/llvm/test/CodeGen/LoongArch/jr-without-ra.ll +++ b/llvm/test/CodeGen/LoongArch/jr-without-ra.ll @@ -38,23 +38,31 @@ define void @jr_without_ra(ptr %rtwdev, ptr %chan, ptr %h2c, i8 %.pre, i1 %cmp.i ; CHECK-NEXT: alsl.d $a6, $a6, $s2, 4 ; CHECK-NEXT: pcalau12i $s2, %pc_hi20(.LJTI0_0) ; CHECK-NEXT: addi.d $s2, $s2, %pc_lo12(.LJTI0_0) -; CHECK-NEXT: ori $s3, $zero, 1 -; CHECK-NEXT: ori $s4, $zero, 50 +; CHECK-NEXT: ori $s3, $zero, 50 +; CHECK-NEXT: ori $s4, $zero, 1 ; CHECK-NEXT: ori $s5, $zero, 3 ; CHECK-NEXT: lu32i.d $s5, 262144 -; CHECK-NEXT: b .LBB0_4 +; CHECK-NEXT: b .LBB0_3 ; CHECK-NEXT: .p2align 4, , 16 -; CHECK-NEXT: .LBB0_1: # %sw.bb27.i.i -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 +; CHECK-NEXT: .LBB0_1: # %if.else58.i +; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 +; CHECK-NEXT: ldx.bu $s6, $a6, $s6 +; CHECK-NEXT: .LBB0_2: # %phy_tssi_get_ofdm_trim_de.exit +; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 +; CHECK-NEXT: st.b $zero, $t8, 0 +; CHECK-NEXT: slli.d $s8, $t1, 2 +; CHECK-NEXT: alsl.d $s8, $t1, $s8, 1 +; CHECK-NEXT: add.d $s8, $t6, $s8 +; CHECK-NEXT: ldx.b $s8, $s8, $t5 +; CHECK-NEXT: st.b $zero, $a2, 0 +; CHECK-NEXT: st.b $zero, $a7, 0 +; CHECK-NEXT: st.b $zero, $t7, 0 +; CHECK-NEXT: st.b $s8, $a0, 0 ; CHECK-NEXT: ori $s7, $zero, 1 -; CHECK-NEXT: .LBB0_2: # %if.else.i106 -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 ; CHECK-NEXT: alsl.d $s8, $s1, $s1, 3 ; CHECK-NEXT: alsl.d $s1, $s8, $s1, 1 ; CHECK-NEXT: add.d $s1, $t0, $s1 ; CHECK-NEXT: ldx.bu $s7, $s1, $s7 -; CHECK-NEXT: .LBB0_3: # %phy_tssi_get_ofdm_de.exit -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 ; CHECK-NEXT: st.b $zero, $t6, 0 ; CHECK-NEXT: st.b $s6, $t4, 0 ; CHECK-NEXT: st.b $zero, $fp, 0 @@ -64,65 +72,31 @@ define void @jr_without_ra(ptr %rtwdev, ptr %chan, ptr %h2c, i8 %.pre, i1 %cmp.i ; CHECK-NEXT: st.b $s7, $a5, 0 ; CHECK-NEXT: ori $s1, $zero, 1 ; CHECK-NEXT: move $s6, $a3 -; CHECK-NEXT: .LBB0_4: # %for.body +; CHECK-NEXT: .LBB0_3: # %for.body ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: beqz $a4, .LBB0_9 -; CHECK-NEXT: # %bb.5: # %calc_6g.i -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 +; CHECK-NEXT: beqz $a4, .LBB0_6 +; CHECK-NEXT: # %bb.4: # %calc_6g.i +; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 ; CHECK-NEXT: move $s6, $zero -; CHECK-NEXT: bnez $zero, .LBB0_8 -; CHECK-NEXT: # %bb.6: # %calc_6g.i -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 ; CHECK-NEXT: slli.d $s7, $zero, 3 ; CHECK-NEXT: ldx.d $s7, $s2, $s7 ; CHECK-NEXT: jr $s7 -; CHECK-NEXT: .LBB0_7: # %sw.bb12.i.i -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 +; CHECK-NEXT: .LBB0_5: # %sw.bb12.i.i +; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 ; CHECK-NEXT: ori $s6, $zero, 1 -; CHECK-NEXT: .LBB0_8: # %if.else58.i -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 -; CHECK-NEXT: ldx.bu $s6, $a6, $s6 -; CHECK-NEXT: b .LBB0_11 +; CHECK-NEXT: b .LBB0_1 ; CHECK-NEXT: .p2align 4, , 16 -; CHECK-NEXT: .LBB0_9: # %if.end.i -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 +; CHECK-NEXT: .LBB0_6: # %if.end.i +; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 ; CHECK-NEXT: andi $s6, $s6, 255 -; CHECK-NEXT: bltu $s4, $s6, .LBB0_15 -; CHECK-NEXT: # %bb.10: # %if.end.i -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 -; CHECK-NEXT: sll.d $s6, $s3, $s6 +; CHECK-NEXT: bltu $s3, $s6, .LBB0_8 +; CHECK-NEXT: # %bb.7: # %if.end.i +; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 +; CHECK-NEXT: sll.d $s6, $s4, $s6 ; CHECK-NEXT: and $s7, $s6, $s5 ; CHECK-NEXT: move $s6, $s0 -; CHECK-NEXT: beqz $s7, .LBB0_15 -; CHECK-NEXT: .LBB0_11: # %phy_tssi_get_ofdm_trim_de.exit -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 -; CHECK-NEXT: move $s7, $zero -; CHECK-NEXT: st.b $zero, $t8, 0 -; CHECK-NEXT: slli.d $s8, $t1, 2 -; CHECK-NEXT: alsl.d $s8, $t1, $s8, 1 -; CHECK-NEXT: add.d $s8, $t6, $s8 -; CHECK-NEXT: ldx.b $s8, $s8, $t5 -; CHECK-NEXT: st.b $zero, $a2, 0 -; CHECK-NEXT: st.b $zero, $a7, 0 -; CHECK-NEXT: st.b $zero, $t7, 0 -; CHECK-NEXT: st.b $s8, $a0, 0 -; CHECK-NEXT: bnez $s3, .LBB0_13 -; CHECK-NEXT: # %bb.12: # %phy_tssi_get_ofdm_trim_de.exit -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 -; CHECK-NEXT: addi.w $s8, $zero, -41 -; CHECK-NEXT: slli.d $s8, $s8, 3 -; CHECK-NEXT: pcalau12i $ra, %pc_hi20(.LJTI0_1) -; CHECK-NEXT: addi.d $ra, $ra, %pc_lo12(.LJTI0_1) -; CHECK-NEXT: ldx.d $s8, $ra, $s8 -; CHECK-NEXT: jr $s8 -; CHECK-NEXT: .LBB0_13: # %phy_tssi_get_ofdm_trim_de.exit -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 -; CHECK-NEXT: bnez $s3, .LBB0_1 -; CHECK-NEXT: # %bb.14: # %phy_tssi_get_ofdm_trim_de.exit -; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1 -; CHECK-NEXT: bnez $zero, .LBB0_3 -; CHECK-NEXT: b .LBB0_2 -; CHECK-NEXT: .LBB0_15: # %sw.bb9.i.i +; CHECK-NEXT: bnez $s7, .LBB0_2 +; CHECK-NEXT: .LBB0_8: # %sw.bb9.i.i ; CHECK-NEXT: ld.d $s8, $sp, 8 # 8-byte Folded Reload ; CHECK-NEXT: ld.d $s7, $sp, 16 # 8-byte Folded Reload ; CHECK-NEXT: ld.d $s6, $sp, 24 # 8-byte Folded Reload diff --git a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll index 4a77cccb99a2e..3bbd6676181d0 100644 --- a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll +++ b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll @@ -152,7 +152,10 @@ ; LAXX-NEXT: Machine Optimization Remark Emitter ; LAXX-NEXT: Shrink Wrapping analysis ; LAXX-NEXT: Prologue/Epilogue Insertion & Frame Finalization +; LAXX-NEXT: LoongArch Late Branch Optimisation Pass ; LAXX-NEXT: Machine Late Instructions Cleanup Pass +; LAXX-NEXT: Machine Cycle Info Analysis +; LAXX-NEXT: Machine Block Frequency Analysis ; LAXX-NEXT: Control Flow Optimizer ; LAXX-NEXT: Lazy Machine Block Frequency Analysis ; LAXX-NEXT: Tail Duplication @@ -160,6 +163,7 @@ ; LAXX-NEXT: Post-RA pseudo instruction expansion pass ; LAXX-NEXT: MachineDominator Tree Construction ; LAXX-NEXT: Machine Natural Loop Construction +; LAXX-NEXT: Machine Register Class Info Analysis ; LAXX-NEXT: Post RA top-down list latency scheduler ; LAXX-NEXT: Analyze Machine Code For Garbage Collection ; LAXX-NEXT: Machine Cycle Info Analysis diff --git a/llvm/test/CodeGen/LoongArch/pr215935.ll b/llvm/test/CodeGen/LoongArch/pr215935.ll index 661f7f9f60f88..9c00ff18ef4cf 100644 --- a/llvm/test/CodeGen/LoongArch/pr215935.ll +++ b/llvm/test/CodeGen/LoongArch/pr215935.ll @@ -4,11 +4,6 @@ define i64 @brcond_const_1(i64 %0) nounwind { ; CHECK-LABEL: brcond_const_1: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: beqz $zero, .LBB0_2 -; CHECK-NEXT: # %bb.1: -; CHECK-NEXT: move $a0, $zero -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB0_2: ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: ret entry: @@ -28,13 +23,8 @@ entry: define i64 @brcond_const_0(i64 %0) nounwind { ; CHECK-LABEL: brcond_const_0: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: bnez $zero, .LBB1_2 -; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: move $a0, $zero ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB1_2: -; CHECK-NEXT: ori $a0, $zero, 1 -; CHECK-NEXT: ret entry: %2 = trunc i64 %0 to i32 %3 = trunc i64 %0 to i8 diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected index c2f5f345624bc..acf0803a1c525 100644 --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected @@ -75,16 +75,6 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; CHECK-NEXT: st.w $zero, $fp, -12 ; CHECK-NEXT: st.w $zero, $fp, -16 ; CHECK-NEXT: ori $a0, $zero, 1 -; CHECK-NEXT: beq $zero, $zero, .LBB0_3 -; CHECK-NEXT: # %bb.1: -; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: ld.w $a0, $fp, -16 -; CHECK-NEXT: beq $a0, $zero, .LBB0_4 -; CHECK-NEXT: .LBB0_2: -; CHECK-NEXT: ori $a0, $zero, 1 -; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: b .LBB0_5 -; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: st.w $a0, $fp, -16 ; CHECK-NEXT: ori $a0, $zero, 2 ; CHECK-NEXT: st.w $a0, $fp, -20 @@ -93,8 +83,12 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; CHECK-NEXT: ori $a0, $zero, 4 ; CHECK-NEXT: st.w $a0, $fp, -28 ; CHECK-NEXT: ld.w $a0, $fp, -16 -; CHECK-NEXT: bne $a0, $zero, .LBB0_2 -; CHECK-NEXT: .LBB0_4: +; CHECK-NEXT: beq $a0, $zero, .LBB0_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: ori $a0, $zero, 1 +; CHECK-NEXT: st.w $a0, $fp, -24 +; CHECK-NEXT: b .LBB0_3 +; CHECK-NEXT: .LBB0_2: ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: st.w $a0, $fp, -16 ; CHECK-NEXT: ori $a0, $zero, 2 @@ -103,7 +97,7 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; CHECK-NEXT: st.w $a0, $fp, -24 ; CHECK-NEXT: ori $a0, $zero, 4 ; CHECK-NEXT: st.w $a0, $fp, -28 -; CHECK-NEXT: .LBB0_5: +; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: move $a0, $zero ; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload ; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected index 1ab256f6fa268..e0d1623f5720a 100644 --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected @@ -16,16 +16,6 @@ define dso_local i32 @check_boundaries() #0 { ; CHECK-NEXT: st.w $zero, $fp, -12 ; CHECK-NEXT: st.w $zero, $fp, -16 ; CHECK-NEXT: ori $a0, $zero, 1 -; CHECK-NEXT: beq $zero, $zero, .LBB0_3 -; CHECK-NEXT: # %bb.1: -; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: ld.w $a0, $fp, -16 -; CHECK-NEXT: beq $a0, $zero, .LBB0_4 -; CHECK-NEXT: .LBB0_2: -; CHECK-NEXT: ori $a0, $zero, 1 -; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: b .LBB0_5 -; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: st.w $a0, $fp, -16 ; CHECK-NEXT: ori $a0, $zero, 2 ; CHECK-NEXT: st.w $a0, $fp, -20 @@ -34,8 +24,12 @@ define dso_local i32 @check_boundaries() #0 { ; CHECK-NEXT: ori $a0, $zero, 4 ; CHECK-NEXT: st.w $a0, $fp, -28 ; CHECK-NEXT: ld.w $a0, $fp, -16 -; CHECK-NEXT: bne $a0, $zero, .LBB0_2 -; CHECK-NEXT: .LBB0_4: +; CHECK-NEXT: beq $a0, $zero, .LBB0_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: ori $a0, $zero, 1 +; CHECK-NEXT: st.w $a0, $fp, -24 +; CHECK-NEXT: b .LBB0_3 +; CHECK-NEXT: .LBB0_2: ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: st.w $a0, $fp, -16 ; CHECK-NEXT: ori $a0, $zero, 2 @@ -44,7 +38,7 @@ define dso_local i32 @check_boundaries() #0 { ; CHECK-NEXT: st.w $a0, $fp, -24 ; CHECK-NEXT: ori $a0, $zero, 4 ; CHECK-NEXT: st.w $a0, $fp, -28 -; CHECK-NEXT: .LBB0_5: +; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: move $a0, $zero ; CHECK-NEXT: ld.w $fp, $sp, 24 # 4-byte Folded Reload ; CHECK-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn index 810811f7d147c..d68ccd8cbee73 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn @@ -48,6 +48,7 @@ static_library("LLVMLoongArchCodeGen") { "LoongArchISelDAGToDAG.cpp", "LoongArchISelLowering.cpp", "LoongArchInstrInfo.cpp", + "LoongArchLateBranchOpt.cpp", "LoongArchMCInstLower.cpp", "LoongArchMergeBaseOffset.cpp", "LoongArchOptWInstrs.cpp", _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
