Path: blob/main/contrib/llvm-project/llvm/lib/Target/ARC/ARCBranchFinalize.cpp
35294 views
//===- ARCBranchFinalize.cpp - ARC conditional branches ---------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This pass takes existing conditional branches and expands them into longer9// range conditional branches.10//===----------------------------------------------------------------------===//1112#include "ARCInstrInfo.h"13#include "ARCTargetMachine.h"14#include "MCTargetDesc/ARCInfo.h"15#include "llvm/CodeGen/MachineFunctionPass.h"16#include "llvm/CodeGen/MachineInstrBuilder.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/CodeGen/Passes.h"19#include "llvm/CodeGen/TargetInstrInfo.h"20#include "llvm/InitializePasses.h"21#include "llvm/Support/Debug.h"22#include <vector>2324#define DEBUG_TYPE "arc-branch-finalize"2526using namespace llvm;2728namespace llvm {2930void initializeARCBranchFinalizePass(PassRegistry &Registry);31FunctionPass *createARCBranchFinalizePass();3233} // end namespace llvm3435namespace {3637class ARCBranchFinalize : public MachineFunctionPass {38public:39static char ID;4041ARCBranchFinalize() : MachineFunctionPass(ID) {42initializeARCBranchFinalizePass(*PassRegistry::getPassRegistry());43}4445StringRef getPassName() const override {46return "ARC Branch Finalization Pass";47}4849bool runOnMachineFunction(MachineFunction &MF) override;50void replaceWithBRcc(MachineInstr *MI) const;51void replaceWithCmpBcc(MachineInstr *MI) const;5253private:54const ARCInstrInfo *TII{nullptr};55};5657char ARCBranchFinalize::ID = 0;5859} // end anonymous namespace6061INITIALIZE_PASS_BEGIN(ARCBranchFinalize, "arc-branch-finalize",62"ARC finalize branches", false, false)63INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)64INITIALIZE_PASS_END(ARCBranchFinalize, "arc-branch-finalize",65"ARC finalize branches", false, false)6667// BRcc has 6 supported condition codes, which differ from the 1668// condition codes supported in the predicated instructions:69// EQ -- 00070// NE -- 00171// LT -- 01072// GE -- 01173// LO -- 10074// HS -- 10175static unsigned getCCForBRcc(unsigned CC) {76switch (CC) {77case ARCCC::EQ:78return 0;79case ARCCC::NE:80return 1;81case ARCCC::LT:82return 2;83case ARCCC::GE:84return 3;85case ARCCC::LO:86return 4;87case ARCCC::HS:88return 5;89default:90return -1U;91}92}9394static bool isBRccPseudo(MachineInstr *MI) {95return !(MI->getOpcode() != ARC::BRcc_rr_p &&96MI->getOpcode() != ARC::BRcc_ru6_p);97}9899static unsigned getBRccForPseudo(MachineInstr *MI) {100assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");101if (MI->getOpcode() == ARC::BRcc_rr_p)102return ARC::BRcc_rr;103return ARC::BRcc_ru6;104}105106static unsigned getCmpForPseudo(MachineInstr *MI) {107assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");108if (MI->getOpcode() == ARC::BRcc_rr_p)109return ARC::CMP_rr;110return ARC::CMP_ru6;111}112113void ARCBranchFinalize::replaceWithBRcc(MachineInstr *MI) const {114LLVM_DEBUG(dbgs() << "Replacing pseudo branch with BRcc\n");115unsigned CC = getCCForBRcc(MI->getOperand(3).getImm());116if (CC != -1U) {117BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),118TII->get(getBRccForPseudo(MI)))119.addMBB(MI->getOperand(0).getMBB())120.addReg(MI->getOperand(1).getReg())121.add(MI->getOperand(2))122.addImm(getCCForBRcc(MI->getOperand(3).getImm()));123MI->eraseFromParent();124} else {125replaceWithCmpBcc(MI);126}127}128129void ARCBranchFinalize::replaceWithCmpBcc(MachineInstr *MI) const {130LLVM_DEBUG(dbgs() << "Branch: " << *MI << "\n");131LLVM_DEBUG(dbgs() << "Replacing pseudo branch with Cmp + Bcc\n");132BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),133TII->get(getCmpForPseudo(MI)))134.addReg(MI->getOperand(1).getReg())135.add(MI->getOperand(2));136BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(ARC::Bcc))137.addMBB(MI->getOperand(0).getMBB())138.addImm(MI->getOperand(3).getImm());139MI->eraseFromParent();140}141142bool ARCBranchFinalize::runOnMachineFunction(MachineFunction &MF) {143LLVM_DEBUG(dbgs() << "Running ARC Branch Finalize on " << MF.getName()144<< "\n");145std::vector<MachineInstr *> Branches;146bool Changed = false;147unsigned MaxSize = 0;148TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();149std::map<MachineBasicBlock *, unsigned> BlockToPCMap;150std::vector<std::pair<MachineInstr *, unsigned>> BranchToPCList;151unsigned PC = 0;152153for (auto &MBB : MF) {154BlockToPCMap.insert(std::make_pair(&MBB, PC));155for (auto &MI : MBB) {156unsigned Size = TII->getInstSizeInBytes(MI);157if (Size > 8 || Size == 0) {158LLVM_DEBUG(dbgs() << "Unknown (or size 0) size for: " << MI << "\n");159} else {160MaxSize += Size;161}162if (MI.isBranch()) {163Branches.push_back(&MI);164BranchToPCList.emplace_back(&MI, PC);165}166PC += Size;167}168}169for (auto P : BranchToPCList) {170if (isBRccPseudo(P.first))171isInt<9>(MaxSize) ? replaceWithBRcc(P.first) : replaceWithCmpBcc(P.first);172}173174LLVM_DEBUG(dbgs() << "Estimated function size for " << MF.getName() << ": "175<< MaxSize << "\n");176177return Changed;178}179180FunctionPass *llvm::createARCBranchFinalizePass() {181return new ARCBranchFinalize();182}183184185