brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 9d616e1 Raw
184 lines · cpp
1//===- ARCBranchFinalize.cpp - ARC conditional branches ---------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This pass takes existing conditional branches and expands them into longer10// range conditional branches.11//===----------------------------------------------------------------------===//12 13#include "ARCInstrInfo.h"14#include "ARCTargetMachine.h"15#include "MCTargetDesc/ARCInfo.h"16#include "llvm/CodeGen/MachineFunctionPass.h"17#include "llvm/CodeGen/MachineInstrBuilder.h"18#include "llvm/CodeGen/MachineRegisterInfo.h"19#include "llvm/CodeGen/Passes.h"20#include "llvm/CodeGen/TargetInstrInfo.h"21#include "llvm/InitializePasses.h"22#include "llvm/Support/Debug.h"23#include <vector>24 25#define DEBUG_TYPE "arc-branch-finalize"26 27using namespace llvm;28 29namespace llvm {30 31void initializeARCBranchFinalizePass(PassRegistry &Registry);32FunctionPass *createARCBranchFinalizePass();33 34} // end namespace llvm35 36namespace {37 38class ARCBranchFinalize : public MachineFunctionPass {39public:40  static char ID;41 42  ARCBranchFinalize() : MachineFunctionPass(ID) {43    initializeARCBranchFinalizePass(*PassRegistry::getPassRegistry());44  }45 46  StringRef getPassName() const override {47    return "ARC Branch Finalization Pass";48  }49 50  bool runOnMachineFunction(MachineFunction &MF) override;51  void replaceWithBRcc(MachineInstr *MI) const;52  void replaceWithCmpBcc(MachineInstr *MI) const;53 54private:55  const ARCInstrInfo *TII{nullptr};56};57 58char ARCBranchFinalize::ID = 0;59 60} // end anonymous namespace61 62INITIALIZE_PASS_BEGIN(ARCBranchFinalize, "arc-branch-finalize",63                      "ARC finalize branches", false, false)64INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)65INITIALIZE_PASS_END(ARCBranchFinalize, "arc-branch-finalize",66                    "ARC finalize branches", false, false)67 68// BRcc has 6 supported condition codes, which differ from the 1669// condition codes supported in the predicated instructions:70// EQ -- 00071// NE -- 00172// LT -- 01073// GE -- 01174// LO -- 10075// HS -- 10176static unsigned getCCForBRcc(unsigned CC) {77  switch (CC) {78  case ARCCC::EQ:79    return 0;80  case ARCCC::NE:81    return 1;82  case ARCCC::LT:83    return 2;84  case ARCCC::GE:85    return 3;86  case ARCCC::LO:87    return 4;88  case ARCCC::HS:89    return 5;90  default:91    return -1U;92  }93}94 95static bool isBRccPseudo(MachineInstr *MI) {96  return !(MI->getOpcode() != ARC::BRcc_rr_p &&97           MI->getOpcode() != ARC::BRcc_ru6_p);98}99 100static unsigned getBRccForPseudo(MachineInstr *MI) {101  assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");102  if (MI->getOpcode() == ARC::BRcc_rr_p)103    return ARC::BRcc_rr;104  return ARC::BRcc_ru6;105}106 107static unsigned getCmpForPseudo(MachineInstr *MI) {108  assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");109  if (MI->getOpcode() == ARC::BRcc_rr_p)110    return ARC::CMP_rr;111  return ARC::CMP_ru6;112}113 114void ARCBranchFinalize::replaceWithBRcc(MachineInstr *MI) const {115  LLVM_DEBUG(dbgs() << "Replacing pseudo branch with BRcc\n");116  unsigned CC = getCCForBRcc(MI->getOperand(3).getImm());117  if (CC != -1U) {118    BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),119            TII->get(getBRccForPseudo(MI)))120        .addMBB(MI->getOperand(0).getMBB())121        .addReg(MI->getOperand(1).getReg())122        .add(MI->getOperand(2))123        .addImm(getCCForBRcc(MI->getOperand(3).getImm()));124    MI->eraseFromParent();125  } else {126    replaceWithCmpBcc(MI);127  }128}129 130void ARCBranchFinalize::replaceWithCmpBcc(MachineInstr *MI) const {131  LLVM_DEBUG(dbgs() << "Branch: " << *MI << "\n");132  LLVM_DEBUG(dbgs() << "Replacing pseudo branch with Cmp + Bcc\n");133  BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),134          TII->get(getCmpForPseudo(MI)))135      .addReg(MI->getOperand(1).getReg())136      .add(MI->getOperand(2));137  BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(ARC::Bcc))138      .addMBB(MI->getOperand(0).getMBB())139      .addImm(MI->getOperand(3).getImm());140  MI->eraseFromParent();141}142 143bool ARCBranchFinalize::runOnMachineFunction(MachineFunction &MF) {144  LLVM_DEBUG(dbgs() << "Running ARC Branch Finalize on " << MF.getName()145                    << "\n");146  std::vector<MachineInstr *> Branches;147  bool Changed = false;148  unsigned MaxSize = 0;149  TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();150  std::map<MachineBasicBlock *, unsigned> BlockToPCMap;151  std::vector<std::pair<MachineInstr *, unsigned>> BranchToPCList;152  unsigned PC = 0;153 154  for (auto &MBB : MF) {155    BlockToPCMap.insert(std::make_pair(&MBB, PC));156    for (auto &MI : MBB) {157      unsigned Size = TII->getInstSizeInBytes(MI);158      if (Size > 8 || Size == 0) {159        LLVM_DEBUG(dbgs() << "Unknown (or size 0) size for: " << MI << "\n");160      } else {161        MaxSize += Size;162      }163      if (MI.isBranch()) {164        Branches.push_back(&MI);165        BranchToPCList.emplace_back(&MI, PC);166      }167      PC += Size;168    }169  }170  for (auto P : BranchToPCList) {171    if (isBRccPseudo(P.first))172      isInt<9>(MaxSize) ? replaceWithBRcc(P.first) : replaceWithCmpBcc(P.first);173  }174 175  LLVM_DEBUG(dbgs() << "Estimated function size for " << MF.getName() << ": "176                    << MaxSize << "\n");177 178  return Changed;179}180 181FunctionPass *llvm::createARCBranchFinalizePass() {182  return new ARCBranchFinalize();183}184