From: wanglei Date: Tue, 9 Aug 2022 05:53:34 +0000 (+0800) Subject: [LoongArch] Implement branch analysis X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8716513e65c4e8eb0530579e3a15e44de88c3b9a;p=platform%2Fupstream%2Fllvm.git [LoongArch] Implement branch analysis This allows a number of optimisation passes to work. E.g. BranchFolding and MachineBlockPlacement. Differential Revision: https://reviews.llvm.org/D131316 --- diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp index bcbd4b2..a927fd5 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -113,3 +113,192 @@ void LoongArchInstrInfo::loadRegFromStackSlot( .addImm(0) .addMemOperand(MMO); } + +unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { + return MI.getDesc().getSize(); +} + +MachineBasicBlock * +LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { + assert(MI.getDesc().isBranch() && "Unexpected opcode!"); + // The branch target is always the last operand. + return MI.getOperand(MI.getNumExplicitOperands() - 1).getMBB(); +} + +static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target, + SmallVectorImpl &Cond) { + // Block ends with fall-through condbranch. + assert(LastInst.getDesc().isConditionalBranch() && + "Unknown conditional branch"); + int NumOp = LastInst.getNumExplicitOperands(); + Target = LastInst.getOperand(NumOp - 1).getMBB(); + + Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode())); + for (int i = 0; i < NumOp - 1; i++) + Cond.push_back(LastInst.getOperand(i)); +} + +bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + TBB = FBB = nullptr; + Cond.clear(); + + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); + if (I == MBB.end() || !isUnpredicatedTerminator(*I)) + return false; + + // Count the number of terminators and find the first unconditional or + // indirect branch. + MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end(); + int NumTerminators = 0; + for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J); + J++) { + NumTerminators++; + if (J->getDesc().isUnconditionalBranch() || + J->getDesc().isIndirectBranch()) { + FirstUncondOrIndirectBr = J.getReverse(); + } + } + + // If AllowModify is true, we can erase any terminators after + // FirstUncondOrIndirectBR. + if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) { + while (std::next(FirstUncondOrIndirectBr) != MBB.end()) { + std::next(FirstUncondOrIndirectBr)->eraseFromParent(); + NumTerminators--; + } + I = FirstUncondOrIndirectBr; + } + + // Handle a single unconditional branch. + if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) { + TBB = getBranchDestBlock(*I); + return false; + } + + // Handle a single conditional branch. + if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) { + parseCondBranch(*I, TBB, Cond); + return false; + } + + // Handle a conditional branch followed by an unconditional branch. + if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() && + I->getDesc().isUnconditionalBranch()) { + parseCondBranch(*std::prev(I), TBB, Cond); + FBB = getBranchDestBlock(*I); + return false; + } + + // Otherwise, we can't handle this. + return true; +} + +unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB, + int *BytesRemoved) const { + if (BytesRemoved) + *BytesRemoved = 0; + MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); + if (I == MBB.end()) + return 0; + + if (!I->getDesc().isBranch()) + return 0; + + // Remove the branch. + if (BytesRemoved) + *BytesRemoved += getInstSizeInBytes(*I); + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) + return 1; + --I; + if (!I->getDesc().isConditionalBranch()) + return 1; + + // Remove the branch. + if (BytesRemoved) + *BytesRemoved += getInstSizeInBytes(*I); + I->eraseFromParent(); + return 2; +} + +// Inserts a branch into the end of the specific MachineBasicBlock, returning +// the number of instructions inserted. +unsigned LoongArchInstrInfo::insertBranch( + MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, + ArrayRef Cond, const DebugLoc &DL, int *BytesAdded) const { + if (BytesAdded) + *BytesAdded = 0; + + // Shouldn't be a fall through. + assert(TBB && "insertBranch must not be told to insert a fallthrough"); + assert(Cond.size() <= 3 && Cond.size() != 1 && + "LoongArch branch conditions have at most two components!"); + + // Unconditional branch. + if (Cond.empty()) { + MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB); + if (BytesAdded) + *BytesAdded += getInstSizeInBytes(MI); + return 1; + } + + // Either a one or two-way conditional branch. + MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); + for (unsigned i = 1; i < Cond.size(); ++i) + MIB.add(Cond[i]); + MIB.addMBB(TBB); + if (BytesAdded) + *BytesAdded += getInstSizeInBytes(*MIB); + + // One-way conditional branch. + if (!FBB) + return 1; + + // Two-way conditional branch. + MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB); + if (BytesAdded) + *BytesAdded += getInstSizeInBytes(MI); + return 2; +} + +static unsigned getOppositeBranchOpc(unsigned Opc) { + switch (Opc) { + default: + llvm_unreachable("Unrecognized conditional branch"); + case LoongArch::BEQ: + return LoongArch::BNE; + case LoongArch::BNE: + return LoongArch::BEQ; + case LoongArch::BEQZ: + return LoongArch::BNEZ; + case LoongArch::BNEZ: + return LoongArch::BEQZ; + case LoongArch::BCEQZ: + return LoongArch::BCNEZ; + case LoongArch::BCNEZ: + return LoongArch::BCEQZ; + case LoongArch::BLT: + return LoongArch::BGE; + case LoongArch::BGE: + return LoongArch::BLT; + case LoongArch::BLTU: + return LoongArch::BGEU; + case LoongArch::BGEU: + return LoongArch::BLTU; + } +} + +bool LoongArchInstrInfo::reverseBranchCondition( + SmallVectorImpl &Cond) const { + assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!"); + Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); + return false; +} diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h index 0a8c86a..3c94f86 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h @@ -40,6 +40,26 @@ public: MachineBasicBlock::iterator MBBI, Register DstReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override; + + unsigned getInstSizeInBytes(const MachineInstr &MI) const override; + + MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) 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; + + bool + reverseBranchCondition(SmallVectorImpl &Cond) const override; }; } // end namespace llvm diff --git a/llvm/test/CodeGen/LoongArch/analyze-branch.ll b/llvm/test/CodeGen/LoongArch/analyze-branch.ll new file mode 100644 index 0000000..8a39b50 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/analyze-branch.ll @@ -0,0 +1,76 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s + +;; This test checks that LLVM can do basic stripping and reapplying of branches +;; to basic blocks. + +declare void @test_true() +declare void @test_false() + +;; !0 corresponds to a branch being taken, !1 to not being taken. +!0 = !{!"branch_weights", i32 64, i32 4} +!1 = !{!"branch_weights", i32 4, i32 64} + +define void @test_bcc_fallthrough_taken(i64 %in) nounwind { +; CHECK-LABEL: test_bcc_fallthrough_taken: +; CHECK: # %bb.0: +; CHECK-NEXT: addi.d $sp, $sp, -16 +; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; CHECK-NEXT: ori $a1, $zero, 42 +; CHECK-NEXT: bne $a0, $a1, .LBB0_3 +; CHECK-NEXT: # %bb.1: # %true +; CHECK-NEXT: bl test_true +; CHECK-NEXT: .LBB0_2: # %true +; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 16 +; CHECK-NEXT: jirl $zero, $ra, 0 +; CHECK-NEXT: .LBB0_3: # %false +; CHECK-NEXT: bl test_false +; CHECK-NEXT: b .LBB0_2 + %tst = icmp eq i64 %in, 42 + br i1 %tst, label %true, label %false, !prof !0 + +;; Expected layout order is: Entry, TrueBlock, FalseBlock +;; Entry->TrueBlock is the common path, which should be taken whenever the +;; conditional branch is false. + +true: + call void @test_true() + ret void + +false: + call void @test_false() + ret void +} + +define void @test_bcc_fallthrough_nottaken(i64 %in) nounwind { +; CHECK-LABEL: test_bcc_fallthrough_nottaken: +; CHECK: # %bb.0: +; CHECK-NEXT: addi.d $sp, $sp, -16 +; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; CHECK-NEXT: ori $a1, $zero, 42 +; CHECK-NEXT: beq $a0, $a1, .LBB1_1 +; CHECK-NEXT: # %bb.3: # %false +; CHECK-NEXT: bl test_false +; CHECK-NEXT: .LBB1_2: # %true +; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 16 +; CHECK-NEXT: jirl $zero, $ra, 0 +; CHECK-NEXT: .LBB1_1: # %true +; CHECK-NEXT: bl test_true +; CHECK-NEXT: b .LBB1_2 + %tst = icmp eq i64 %in, 42 + br i1 %tst, label %true, label %false, !prof !1 + +;; Expected layout order is: Entry, FalseBlock, TrueBlock +;; Entry->FalseBlock is the common path, which should be taken whenever the +;; conditional branch is false. + +true: + call void @test_true() + ret void + +false: + call void @test_false() + ret void +} diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll index f46eca26..a0074f7 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/br.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=ALL,LA32 ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=ALL,LA64 @@ -18,8 +19,7 @@ define void @foo_br_eq(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: beq $a2, $a0, .LBB1_2 -; LA32-NEXT: b .LBB1_1 -; LA32-NEXT: .LBB1_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB1_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -29,8 +29,7 @@ define void @foo_br_eq(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.wu $a2, $a1, 0 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: beq $a2, $a0, .LBB1_2 -; LA64-NEXT: b .LBB1_1 -; LA64-NEXT: .LBB1_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB1_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -50,8 +49,7 @@ define void @foo_br_ne(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: bne $a2, $a0, .LBB2_2 -; LA32-NEXT: b .LBB2_1 -; LA32-NEXT: .LBB2_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB2_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -61,8 +59,7 @@ define void @foo_br_ne(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.wu $a2, $a1, 0 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: bne $a2, $a0, .LBB2_2 -; LA64-NEXT: b .LBB2_1 -; LA64-NEXT: .LBB2_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB2_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -82,8 +79,7 @@ define void @foo_br_slt(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: blt $a2, $a0, .LBB3_2 -; LA32-NEXT: b .LBB3_1 -; LA32-NEXT: .LBB3_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB3_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -93,8 +89,7 @@ define void @foo_br_slt(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.w $a2, $a1, 0 ; LA64-NEXT: addi.w $a0, $a0, 0 ; LA64-NEXT: blt $a2, $a0, .LBB3_2 -; LA64-NEXT: b .LBB3_1 -; LA64-NEXT: .LBB3_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB3_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -114,8 +109,7 @@ define void @foo_br_sge(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: bge $a2, $a0, .LBB4_2 -; LA32-NEXT: b .LBB4_1 -; LA32-NEXT: .LBB4_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB4_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -125,8 +119,7 @@ define void @foo_br_sge(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.w $a2, $a1, 0 ; LA64-NEXT: addi.w $a0, $a0, 0 ; LA64-NEXT: bge $a2, $a0, .LBB4_2 -; LA64-NEXT: b .LBB4_1 -; LA64-NEXT: .LBB4_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB4_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -146,8 +139,7 @@ define void @foo_br_ult(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: bltu $a2, $a0, .LBB5_2 -; LA32-NEXT: b .LBB5_1 -; LA32-NEXT: .LBB5_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB5_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -157,8 +149,7 @@ define void @foo_br_ult(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.wu $a2, $a1, 0 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: bltu $a2, $a0, .LBB5_2 -; LA64-NEXT: b .LBB5_1 -; LA64-NEXT: .LBB5_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB5_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -178,8 +169,7 @@ define void @foo_br_uge(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: bgeu $a2, $a0, .LBB6_2 -; LA32-NEXT: b .LBB6_1 -; LA32-NEXT: .LBB6_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB6_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -189,8 +179,7 @@ define void @foo_br_uge(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.wu $a2, $a1, 0 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: bgeu $a2, $a0, .LBB6_2 -; LA64-NEXT: b .LBB6_1 -; LA64-NEXT: .LBB6_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB6_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -211,8 +200,7 @@ define void @foo_br_sgt(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: blt $a0, $a2, .LBB7_2 -; LA32-NEXT: b .LBB7_1 -; LA32-NEXT: .LBB7_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB7_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -222,8 +210,7 @@ define void @foo_br_sgt(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.w $a2, $a1, 0 ; LA64-NEXT: addi.w $a0, $a0, 0 ; LA64-NEXT: blt $a0, $a2, .LBB7_2 -; LA64-NEXT: b .LBB7_1 -; LA64-NEXT: .LBB7_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB7_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -243,8 +230,7 @@ define void @foo_br_sle(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: bge $a0, $a2, .LBB8_2 -; LA32-NEXT: b .LBB8_1 -; LA32-NEXT: .LBB8_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB8_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -254,8 +240,7 @@ define void @foo_br_sle(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.w $a2, $a1, 0 ; LA64-NEXT: addi.w $a0, $a0, 0 ; LA64-NEXT: bge $a0, $a2, .LBB8_2 -; LA64-NEXT: b .LBB8_1 -; LA64-NEXT: .LBB8_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB8_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -275,8 +260,7 @@ define void @foo_br_ugt(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: bltu $a0, $a2, .LBB9_2 -; LA32-NEXT: b .LBB9_1 -; LA32-NEXT: .LBB9_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB9_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -286,8 +270,7 @@ define void @foo_br_ugt(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.wu $a2, $a1, 0 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: bltu $a0, $a2, .LBB9_2 -; LA64-NEXT: b .LBB9_1 -; LA64-NEXT: .LBB9_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB9_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -307,8 +290,7 @@ define void @foo_br_ule(i32 %a, ptr %b) nounwind { ; LA32: # %bb.0: ; LA32-NEXT: ld.w $a2, $a1, 0 ; LA32-NEXT: bgeu $a0, $a2, .LBB10_2 -; LA32-NEXT: b .LBB10_1 -; LA32-NEXT: .LBB10_1: # %test +; LA32-NEXT: # %bb.1: # %test ; LA32-NEXT: ld.w $a0, $a1, 0 ; LA32-NEXT: .LBB10_2: # %end ; LA32-NEXT: jirl $zero, $ra, 0 @@ -318,8 +300,7 @@ define void @foo_br_ule(i32 %a, ptr %b) nounwind { ; LA64-NEXT: ld.wu $a2, $a1, 0 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: bgeu $a0, $a2, .LBB10_2 -; LA64-NEXT: b .LBB10_1 -; LA64-NEXT: .LBB10_1: # %test +; LA64-NEXT: # %bb.1: # %test ; LA64-NEXT: ld.w $a0, $a1, 0 ; LA64-NEXT: .LBB10_2: # %end ; LA64-NEXT: jirl $zero, $ra, 0 @@ -342,8 +323,7 @@ define void @foo_br_cc(ptr %a, i1 %cc) nounwind { ; ALL-NEXT: ld.w $a2, $a0, 0 ; ALL-NEXT: andi $a1, $a1, 1 ; ALL-NEXT: bnez $a1, .LBB11_2 -; ALL-NEXT: b .LBB11_1 -; ALL-NEXT: .LBB11_1: # %test +; ALL-NEXT: # %bb.1: # %test ; ALL-NEXT: ld.w $a0, $a0, 0 ; ALL-NEXT: .LBB11_2: # %end ; ALL-NEXT: jirl $zero, $ra, 0 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 5d091d7..fa82e38 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 @@ -74,24 +74,16 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" } ; CHECK-NEXT: .cfi_def_cfa 22, 0 ; CHECK-NEXT: st.w $zero, $fp, -16 ; CHECK-NEXT: st.w $zero, $fp, -12 -; CHECK-NEXT: bnez $zero, .LBB0_2 -; CHECK-NEXT: b .LBB0_1 -; CHECK-NEXT: .LBB0_2: +; CHECK-NEXT: beqz $zero, .LBB0_1 +; CHECK-NEXT: # %bb.2: ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: ld.w $a0, $fp, -16 -; CHECK-NEXT: bne $a0, $zero, .LBB0_5 -; CHECK-NEXT: b .LBB0_4 +; CHECK-NEXT: beq $a0, $zero, .LBB0_4 ; CHECK-NEXT: .LBB0_5: ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: .LBB0_6: -; 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 -; CHECK-NEXT: addi.w $sp, $sp, 32 -; CHECK-NEXT: jirl $zero, $ra, 0 +; CHECK-NEXT: b .LBB0_6 ; CHECK-NEXT: .LBB0_1: ; CHECK-NEXT: ori $a0, $zero, 2 ; CHECK-NEXT: st.w $a0, $fp, -20 @@ -101,7 +93,8 @@ 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: b .LBB0_3 +; CHECK-NEXT: ld.w $a0, $fp, -16 +; CHECK-NEXT: bne $a0, $zero, .LBB0_5 ; CHECK-NEXT: .LBB0_4: ; CHECK-NEXT: ori $a0, $zero, 2 ; CHECK-NEXT: st.w $a0, $fp, -20 @@ -111,7 +104,12 @@ 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: b .LBB0_6 +; CHECK-NEXT: .LBB0_6: +; 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 +; CHECK-NEXT: addi.w $sp, $sp, 32 +; CHECK-NEXT: jirl $zero, $ra, 0 ; ; CHECK-LABEL: main: ; CHECK: # %bb.0: 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 d4edfe5..baf0839 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 @@ -15,24 +15,16 @@ define dso_local i32 @check_boundaries() #0 { ; CHECK-NEXT: .cfi_def_cfa 22, 0 ; CHECK-NEXT: st.w $zero, $fp, -16 ; CHECK-NEXT: st.w $zero, $fp, -12 -; CHECK-NEXT: bnez $zero, .LBB0_2 -; CHECK-NEXT: b .LBB0_1 -; CHECK-NEXT: .LBB0_2: +; CHECK-NEXT: beqz $zero, .LBB0_1 +; CHECK-NEXT: # %bb.2: ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: ld.w $a0, $fp, -16 -; CHECK-NEXT: bne $a0, $zero, .LBB0_5 -; CHECK-NEXT: b .LBB0_4 +; CHECK-NEXT: beq $a0, $zero, .LBB0_4 ; CHECK-NEXT: .LBB0_5: ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: st.w $a0, $fp, -24 -; CHECK-NEXT: .LBB0_6: -; 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 -; CHECK-NEXT: addi.w $sp, $sp, 32 -; CHECK-NEXT: jirl $zero, $ra, 0 +; CHECK-NEXT: b .LBB0_6 ; CHECK-NEXT: .LBB0_1: ; CHECK-NEXT: ori $a0, $zero, 2 ; CHECK-NEXT: st.w $a0, $fp, -20 @@ -42,7 +34,8 @@ 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: b .LBB0_3 +; CHECK-NEXT: ld.w $a0, $fp, -16 +; CHECK-NEXT: bne $a0, $zero, .LBB0_5 ; CHECK-NEXT: .LBB0_4: ; CHECK-NEXT: ori $a0, $zero, 2 ; CHECK-NEXT: st.w $a0, $fp, -20 @@ -52,7 +45,12 @@ 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: b .LBB0_6 +; CHECK-NEXT: .LBB0_6: +; 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 +; CHECK-NEXT: addi.w $sp, $sp, 32 +; CHECK-NEXT: jirl $zero, $ra, 0 %1 = alloca i32, align 4 %2 = alloca i32, align 4 %3 = alloca i32, align 4