
This patch is an alternative to PRs #117060, #131684, #131728. The patch adds a late optimization pass that replaces conditional branches that can be statically evaluated with an unconditinal branch. Adding Michael as a co-author as most of the code that evaluates the condition comes from #131684. Co-authored-by: Michael Maitland michaeltmaitland@gmail.com
112 lines
3.3 KiB
C++
112 lines
3.3 KiB
C++
//===-- RISCVLateBranchOpt.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 RISC-V specific target optimizations, currently it's
|
|
/// limited to convert conditional branches into unconditional branches when
|
|
/// the condition can be statically evaluated.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "RISCVInstrInfo.h"
|
|
#include "RISCVSubtarget.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define RISCV_LATE_BRANCH_OPT_NAME "RISC-V Late Branch Optimisation Pass"
|
|
|
|
namespace {
|
|
|
|
struct RISCVLateBranchOpt : public MachineFunctionPass {
|
|
static char ID;
|
|
|
|
RISCVLateBranchOpt() : MachineFunctionPass(ID) {}
|
|
|
|
StringRef getPassName() const override { return RISCV_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 RISCVInstrInfo *RII = nullptr;
|
|
};
|
|
} // namespace
|
|
|
|
char RISCVLateBranchOpt::ID = 0;
|
|
INITIALIZE_PASS(RISCVLateBranchOpt, "riscv-late-branch-opt",
|
|
RISCV_LATE_BRANCH_OPT_NAME, false, false)
|
|
|
|
bool RISCVLateBranchOpt::runOnBasicBlock(MachineBasicBlock &MBB) const {
|
|
MachineBasicBlock *TBB, *FBB;
|
|
SmallVector<MachineOperand, 4> Cond;
|
|
if (RII->analyzeBranch(MBB, TBB, FBB, Cond, /*AllowModify=*/false))
|
|
return false;
|
|
|
|
if (!TBB || Cond.size() != 3)
|
|
return false;
|
|
|
|
RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
|
|
assert(CC != RISCVCC::COND_INVALID);
|
|
|
|
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
|
|
|
|
// Try and convert a conditional branch that can be evaluated statically
|
|
// into an unconditional branch.
|
|
int64_t C0, C1;
|
|
if (!RISCVInstrInfo::isFromLoadImm(MRI, Cond[1], C0) ||
|
|
!RISCVInstrInfo::isFromLoadImm(MRI, Cond[2], C1))
|
|
return false;
|
|
|
|
MachineBasicBlock *Folded =
|
|
RISCVInstrInfo::evaluateCondBranch(CC, C0, C1) ? TBB : FBB;
|
|
|
|
// At this point, its legal to optimize.
|
|
RII->removeBranch(MBB);
|
|
|
|
// Only need to insert a branch if we're not falling through.
|
|
if (Folded) {
|
|
DebugLoc DL = MBB.findBranchDebugLoc();
|
|
RII->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 RISCVLateBranchOpt::runOnMachineFunction(MachineFunction &Fn) {
|
|
if (skipFunction(Fn.getFunction()))
|
|
return false;
|
|
|
|
auto &ST = Fn.getSubtarget<RISCVSubtarget>();
|
|
RII = ST.getInstrInfo();
|
|
|
|
bool Changed = false;
|
|
for (MachineBasicBlock &MBB : Fn)
|
|
Changed |= runOnBasicBlock(MBB);
|
|
return Changed;
|
|
}
|
|
|
|
FunctionPass *llvm::createRISCVLateBranchOptPass() {
|
|
return new RISCVLateBranchOpt();
|
|
}
|