[llvm] Add late optimization pass for riscv (PR #117060)
Mikhail R. Gadelha via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 20 13:36:57 PST 2024
https://github.com/mikhailramalho created https://github.com/llvm/llvm-project/pull/117060
This patch adds a late opt pass (riscv only) to remove blocks with a single instruction, a `beqz` or `bnez` that compares the zero register.
TODO: the branch probability is wrong for the new block:
```
bb.1 (%ir-block.3):
; predecessors: %bb.0
successors: %bb.4(0x80000000), %bb.3(0x00000000); %bb.4(100.00%), %bb.3(0.00%) ; <---- it should be 50%
liveins: $x10
renamable $x10 = XORI killed renamable $x10, -1
renamable $x10 = BEXTI killed renamable $x10, 13
BNE killed renamable $x10, $x0, %bb.4
```
>From a0b48677b97a58326854668eb6183aa9de6c1fbe Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Wed, 20 Nov 2024 18:22:55 -0300
Subject: [PATCH 1/3] Add late optimization pass for riscv
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/lib/Target/RISCV/CMakeLists.txt | 1 +
llvm/lib/Target/RISCV/RISCV.h | 3 +
llvm/lib/Target/RISCV/RISCVLatePeephole.cpp | 157 +++++++++++++++++++
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 2 +
4 files changed, 163 insertions(+)
create mode 100644 llvm/lib/Target/RISCV/RISCVLatePeephole.cpp
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index fd049d1a57860e..d4eb016455b6dd 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -34,6 +34,7 @@ add_llvm_target(RISCVCodeGen
RISCVConstantPoolValue.cpp
RISCVDeadRegisterDefinitions.cpp
RISCVMakeCompressible.cpp
+ RISCVLatePeephole.cpp
RISCVExpandAtomicPseudoInsts.cpp
RISCVExpandPseudoInsts.cpp
RISCVFrameLowering.cpp
diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h
index d7bab601d545cc..2e682eabd6e021 100644
--- a/llvm/lib/Target/RISCV/RISCV.h
+++ b/llvm/lib/Target/RISCV/RISCV.h
@@ -40,6 +40,9 @@ void initializeRISCVLandingPadSetupPass(PassRegistry &);
FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM,
CodeGenOptLevel OptLevel);
+FunctionPass *createRISCVLatePeepholeOptPass();
+void initializeRISCVLatePeepholeOptPass(PassRegistry &);
+
FunctionPass *createRISCVMakeCompressibleOptPass();
void initializeRISCVMakeCompressibleOptPass(PassRegistry &);
diff --git a/llvm/lib/Target/RISCV/RISCVLatePeephole.cpp b/llvm/lib/Target/RISCV/RISCVLatePeephole.cpp
new file mode 100644
index 00000000000000..11add97aa8413e
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVLatePeephole.cpp
@@ -0,0 +1,157 @@
+//===-- RISCVLatePeephole.cpp - Late stage peephole 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 RISC-V specific target descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "RISCV.h"
+#include "RISCVInstrInfo.h"
+#include "RISCVSubtarget.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-late-peephole"
+#define RISCV_LATE_PEEPHOLE_NAME "RISC-V Late Stage Peephole"
+
+namespace {
+
+struct RISCVLatePeepholeOpt : public MachineFunctionPass {
+ static char ID;
+
+ RISCVLatePeepholeOpt() : MachineFunctionPass(ID) {}
+
+ StringRef getPassName() const override { return RISCV_LATE_PEEPHOLE_NAME; }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<MachineDominatorTreeWrapperPass>();
+ AU.addPreserved<MachineDominatorTreeWrapperPass>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ bool runOnMachineFunction(MachineFunction &Fn) override;
+
+private:
+ void removeBlock(MachineBasicBlock *B, MachineBasicBlock *NewB);
+ bool removeSingleBranchBlock(MachineBasicBlock *B);
+
+ const RISCVInstrInfo *RII = nullptr;
+ MachineFunction *MFN = nullptr;
+ MachineDominatorTree *MDT = nullptr;
+};
+} // namespace
+
+char RISCVLatePeepholeOpt::ID = 0;
+INITIALIZE_PASS(RISCVLatePeepholeOpt, "riscv-late-peephole",
+ RISCV_LATE_PEEPHOLE_NAME, false, false)
+
+void RISCVLatePeepholeOpt::removeBlock(MachineBasicBlock *B, MachineBasicBlock *NewB) {
+ LLVM_DEBUG(dbgs() << "Removing block '#'" << B->getNumber() << "\n");
+
+ // Transfer the immediate dominator information from B to its descendants.
+ MachineDomTreeNode *N = MDT->getNode(B);
+ MachineDomTreeNode *IDN = N->getIDom();
+ if (IDN) {
+ MachineBasicBlock *IDB = IDN->getBlock();
+
+ using GTN = GraphTraits<MachineDomTreeNode *>;
+ using DTNodeVectType = SmallVector<MachineDomTreeNode *, 4>;
+
+ DTNodeVectType Cn(GTN::child_begin(N), GTN::child_end(N));
+ for (auto &I : Cn) {
+ MachineBasicBlock *SB = I->getBlock();
+ MDT->changeImmediateDominator(SB, IDB);
+ }
+ }
+
+ while (!B->succ_empty())
+ B->removeSuccessor(B->succ_begin());
+
+ for (MachineBasicBlock *Pred : B->predecessors()) {
+ Pred->removeSuccessor(B, true);
+ // TODO: how do I calculate the branch probability here?
+ if (Pred != NewB)
+ Pred->addSuccessor(NewB);
+ }
+
+ MDT->eraseNode(B);
+ MFN->erase(B->getIterator());
+}
+
+bool RISCVLatePeepholeOpt::removeSingleBranchBlock(MachineBasicBlock *B) {
+ LLVM_DEBUG(dbgs() << "Checking flow pattern at " << printMBBReference(*B)
+ << "\n");
+
+ if (B->size() != 1)
+ return false;
+
+ MachineBasicBlock::const_iterator T1I = B->getFirstTerminator();
+ if (T1I == B->end())
+ return false;
+ unsigned Opc = T1I->getOpcode();
+ if (Opc != RISCV::BEQ && Opc != RISCV::BNE)
+ return false;
+
+ Register DstReg = T1I->getOperand(0).getReg();
+ Register SrcReg = T1I->getOperand(1).getReg();
+ if (DstReg != SrcReg)
+ return false;
+
+ // Get the layout successor, or 0 if B does not have one.
+ MachineFunction::iterator NextBI = std::next(MachineFunction::iterator(B));
+ MachineBasicBlock *NextB = (NextBI != MFN->end()) ? &*NextBI : nullptr;
+
+ MachineBasicBlock *T1B = T1I->getOperand(2).getMBB();
+ assert(std::next(T1I) == B->end());
+
+ MachineBasicBlock *T2B = NextB;
+
+ MachineBasicBlock *PredB = B;
+ MachineBasicBlock *SuccB = Opc == RISCV::BEQ ? T1B : T2B;
+ MachineBasicBlock *DiscB = Opc == RISCV::BEQ ? T2B : T1B;
+
+ LLVM_DEBUG(dbgs() << "Merging blocks '#'" << PredB->getNumber() << " and '#'"
+ << SuccB->getNumber() << "\n");
+
+ RII->removeBranch(*PredB);
+ PredB->removeSuccessor(DiscB);
+ PredB->splice(PredB->end(), SuccB, SuccB->begin(), SuccB->end());
+ removeBlock(SuccB, PredB);
+ return true;
+}
+
+bool RISCVLatePeepholeOpt::runOnMachineFunction(MachineFunction &Fn) {
+ if (skipFunction(Fn.getFunction()))
+ return false;
+
+ auto &ST = Fn.getSubtarget<RISCVSubtarget>();
+ RII = ST.getInstrInfo();
+ MFN = &Fn;
+ MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+
+ bool Changed = false;
+
+ for (MachineBasicBlock &MBB : Fn)
+ Changed |= removeSingleBranchBlock(&MBB);
+
+ return Changed;
+}
+
+/// Returns an instance of the Make Compressible Optimization pass.
+FunctionPass *llvm::createRISCVLatePeepholeOptPass() {
+ return new RISCVLatePeepholeOpt();
+}
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index fa507653264ccd..4e431fef4a82db 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -124,6 +124,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
initializeRISCVPostLegalizerCombinerPass(*PR);
initializeKCFIPass(*PR);
initializeRISCVDeadRegisterDefinitionsPass(*PR);
+ initializeRISCVLatePeepholeOptPass(*PR);
initializeRISCVMakeCompressibleOptPass(*PR);
initializeRISCVGatherScatterLoweringPass(*PR);
initializeRISCVCodeGenPreparePass(*PR);
@@ -552,6 +553,7 @@ void RISCVPassConfig::addPreEmitPass() {
EnableRISCVCopyPropagation)
addPass(createMachineCopyPropagationPass(true));
addPass(&BranchRelaxationPassID);
+ addPass(createRISCVLatePeepholeOptPass());
addPass(createRISCVMakeCompressibleOptPass());
}
>From ed5cde82fd0d06d8499fe556b822c6b4c61d4282 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Wed, 20 Nov 2024 18:28:01 -0300
Subject: [PATCH 2/3] Added test
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/test/CodeGen/RISCV/beqz-zero.ll | 61 ++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/beqz-zero.ll
diff --git a/llvm/test/CodeGen/RISCV/beqz-zero.ll b/llvm/test/CodeGen/RISCV/beqz-zero.ll
new file mode 100644
index 00000000000000..fcb909941b562e
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/beqz-zero.ll
@@ -0,0 +1,61 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefixes=RV32 %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefixes=RV64 %s
+
+
+define i32 @foo(i32 %0, i1 %1) {
+; RV32-LABEL: foo:
+; RV32: # %bb.0:
+; RV32-NEXT: andi a1, a1, 1
+; RV32-NEXT: beqz a1, .LBB0_3
+; RV32-NEXT: # %bb.1:
+; RV32-NEXT: not a0, a0
+; RV32-NEXT: slli a0, a0, 18
+; RV32-NEXT: srli a0, a0, 31
+; RV32-NEXT: bnez a0, .LBB0_4
+; RV32-NEXT: .LBB0_2:
+; RV32-NEXT: lui a0, 912096
+; RV32-NEXT: addi a0, a0, -1330
+; RV32-NEXT: ret
+; RV32-NEXT: .LBB0_3:
+; RV32-NEXT: beqz zero, .LBB0_2
+; RV32-NEXT: .LBB0_4:
+; RV32-NEXT: li a0, 1
+; RV32-NEXT: ret
+;
+; RV64-LABEL: foo:
+; RV64: # %bb.0:
+; RV64-NEXT: andi a1, a1, 1
+; RV64-NEXT: beqz a1, .LBB0_3
+; RV64-NEXT: # %bb.1:
+; RV64-NEXT: not a0, a0
+; RV64-NEXT: slli a0, a0, 50
+; RV64-NEXT: srli a0, a0, 63
+; RV64-NEXT: bnez a0, .LBB0_4
+; RV64-NEXT: .LBB0_2:
+; RV64-NEXT: lui a0, 912096
+; RV64-NEXT: addiw a0, a0, -1330
+; RV64-NEXT: ret
+; RV64-NEXT: .LBB0_3:
+; RV64-NEXT: beqz zero, .LBB0_2
+; RV64-NEXT: .LBB0_4:
+; RV64-NEXT: li a0, 1
+; RV64-NEXT: ret
+ br i1 %1, label %3, label %7
+
+3: ; preds = %2
+ %4 = lshr i32 %0, 13
+ %5 = and i32 %4, 1
+ %6 = xor i32 %5, 1
+ br label %7
+
+7: ; preds = %3, %2
+ %8 = phi i32 [ %6, %3 ], [ 0, %2 ]
+ %9 = icmp eq i32 %8, 0
+ %10 = select i1 %9, i32 -559023410, i32 1
+ ret i32 %10
+}
+
+
>From f75f6a174387487d99d1c98a44bdbd56fec6fc6b Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Wed, 20 Nov 2024 18:30:53 -0300
Subject: [PATCH 3/3] Update test case with new opt
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/test/CodeGen/RISCV/beqz-zero.ll | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/beqz-zero.ll b/llvm/test/CodeGen/RISCV/beqz-zero.ll
index fcb909941b562e..adc48a7ec8acb3 100644
--- a/llvm/test/CodeGen/RISCV/beqz-zero.ll
+++ b/llvm/test/CodeGen/RISCV/beqz-zero.ll
@@ -15,12 +15,10 @@ define i32 @foo(i32 %0, i1 %1) {
; RV32-NEXT: slli a0, a0, 18
; RV32-NEXT: srli a0, a0, 31
; RV32-NEXT: bnez a0, .LBB0_4
-; RV32-NEXT: .LBB0_2:
+; RV32-NEXT: .LBB0_3:
; RV32-NEXT: lui a0, 912096
; RV32-NEXT: addi a0, a0, -1330
; RV32-NEXT: ret
-; RV32-NEXT: .LBB0_3:
-; RV32-NEXT: beqz zero, .LBB0_2
; RV32-NEXT: .LBB0_4:
; RV32-NEXT: li a0, 1
; RV32-NEXT: ret
@@ -34,12 +32,10 @@ define i32 @foo(i32 %0, i1 %1) {
; RV64-NEXT: slli a0, a0, 50
; RV64-NEXT: srli a0, a0, 63
; RV64-NEXT: bnez a0, .LBB0_4
-; RV64-NEXT: .LBB0_2:
+; RV64-NEXT: .LBB0_3:
; RV64-NEXT: lui a0, 912096
; RV64-NEXT: addiw a0, a0, -1330
; RV64-NEXT: ret
-; RV64-NEXT: .LBB0_3:
-; RV64-NEXT: beqz zero, .LBB0_2
; RV64-NEXT: .LBB0_4:
; RV64-NEXT: li a0, 1
; RV64-NEXT: ret
More information about the llvm-commits
mailing list