LLVM  10.0.0svn
ARCBranchFinalize.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass takes existing conditional branches and expands them into longer
10 // range conditional branches.
11 //===----------------------------------------------------------------------===//
12 
13 #define DEBUG_TYPE "arc-branch-finalize"
14 
15 #include "ARCInstrInfo.h"
16 #include "ARCTargetMachine.h"
17 #include "MCTargetDesc/ARCInfo.h"
21 #include "llvm/CodeGen/Passes.h"
23 #include "llvm/Support/Debug.h"
24 #include <vector>
25 
26 using namespace llvm;
27 
28 namespace llvm {
29 
32 
33 } // end namespace llvm
34 
35 namespace {
36 
37 class ARCBranchFinalize : public MachineFunctionPass {
38 public:
39  static char ID;
40 
41  ARCBranchFinalize() : MachineFunctionPass(ID) {
43  }
44 
45  StringRef getPassName() const override {
46  return "ARC Branch Finalization Pass";
47  }
48 
49  bool runOnMachineFunction(MachineFunction &MF) override;
50  void replaceWithBRcc(MachineInstr *MI) const;
51  void replaceWithCmpBcc(MachineInstr *MI) const;
52 
53 private:
54  const ARCInstrInfo *TII{nullptr};
55 };
56 
57 char ARCBranchFinalize::ID = 0;
58 
59 } // end anonymous namespace
60 
61 INITIALIZE_PASS_BEGIN(ARCBranchFinalize, "arc-branch-finalize",
62  "ARC finalize branches", false, false)
64 INITIALIZE_PASS_END(ARCBranchFinalize, "arc-branch-finalize",
65  "ARC finalize branches", false, false)
66 
67 // BRcc has 6 supported condition codes, which differ from the 16
68 // condition codes supported in the predicated instructions:
69 // EQ -- 000
70 // NE -- 001
71 // LT -- 010
72 // GE -- 011
73 // LO -- 100
74 // HS -- 101
75 static unsigned getCCForBRcc(unsigned CC) {
76  switch (CC) {
77  case ARCCC::EQ:
78  return 0;
79  case ARCCC::NE:
80  return 1;
81  case ARCCC::LT:
82  return 2;
83  case ARCCC::GE:
84  return 3;
85  case ARCCC::LO:
86  return 4;
87  case ARCCC::HS:
88  return 5;
89  default:
90  return -1U;
91  }
92 }
93 
94 static bool isBRccPseudo(MachineInstr *MI) {
95  return !(MI->getOpcode() != ARC::BRcc_rr_p &&
96  MI->getOpcode() != ARC::BRcc_ru6_p);
97 }
98 
99 static unsigned getBRccForPseudo(MachineInstr *MI) {
100  assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");
101  if (MI->getOpcode() == ARC::BRcc_rr_p)
102  return ARC::BRcc_rr;
103  return ARC::BRcc_ru6;
104 }
105 
106 static unsigned getCmpForPseudo(MachineInstr *MI) {
107  assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");
108  if (MI->getOpcode() == ARC::BRcc_rr_p)
109  return ARC::CMP_rr;
110  return ARC::CMP_ru6;
111 }
112 
113 void ARCBranchFinalize::replaceWithBRcc(MachineInstr *MI) const {
114  LLVM_DEBUG(dbgs() << "Replacing pseudo branch with BRcc\n");
115  unsigned CC = getCCForBRcc(MI->getOperand(3).getImm());
116  if (CC != -1U) {
117  BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
118  TII->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()));
123  MI->eraseFromParent();
124  } else {
125  replaceWithCmpBcc(MI);
126  }
127 }
128 
129 void ARCBranchFinalize::replaceWithCmpBcc(MachineInstr *MI) const {
130  LLVM_DEBUG(dbgs() << "Branch: " << *MI << "\n");
131  LLVM_DEBUG(dbgs() << "Replacing pseudo branch with Cmp + Bcc\n");
132  BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
133  TII->get(getCmpForPseudo(MI)))
134  .addReg(MI->getOperand(1).getReg())
135  .add(MI->getOperand(2));
136  BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(ARC::Bcc))
137  .addMBB(MI->getOperand(0).getMBB())
138  .addImm(MI->getOperand(3).getImm());
139  MI->eraseFromParent();
140 }
141 
142 bool ARCBranchFinalize::runOnMachineFunction(MachineFunction &MF) {
143  LLVM_DEBUG(dbgs() << "Running ARC Branch Finalize on " << MF.getName()
144  << "\n");
145  std::vector<MachineInstr *> Branches;
146  bool Changed = false;
147  unsigned MaxSize = 0;
148  TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
149  std::map<MachineBasicBlock *, unsigned> BlockToPCMap;
150  std::vector<std::pair<MachineInstr *, unsigned>> BranchToPCList;
151  unsigned PC = 0;
152 
153  for (auto &MBB : MF) {
154  BlockToPCMap.insert(std::make_pair(&MBB, PC));
155  for (auto &MI : MBB) {
156  unsigned Size = TII->getInstSizeInBytes(MI);
157  if (Size > 8 || Size == 0) {
158  LLVM_DEBUG(dbgs() << "Unknown (or size 0) size for: " << MI << "\n");
159  } else {
160  MaxSize += Size;
161  }
162  if (MI.isBranch()) {
163  Branches.push_back(&MI);
164  BranchToPCList.emplace_back(&MI, PC);
165  }
166  PC += Size;
167  }
168  }
169  for (auto P : BranchToPCList) {
170  if (isBRccPseudo(P.first))
171  isInt<9>(MaxSize) ? replaceWithBRcc(P.first) : replaceWithCmpBcc(P.first);
172  }
173 
174  LLVM_DEBUG(dbgs() << "Estimated function size for " << MF.getName() << ": "
175  << MaxSize << "\n");
176 
177  return Changed;
178 }
179 
181  return new ARCBranchFinalize();
182 }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
Definition: AllocatorList.h:23
arc branch finalize
arc branch ARC finalize branches
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:384
void initializeARCBranchFinalizePass(PassRegistry &Registry)
A global registry used in conjunction with static constructors to make pluggable components (like tar...
Definition: Registry.h:44
static bool isBRccPseudo(MachineInstr *MI)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:50
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
arc branch ARC finalize static false unsigned getCCForBRcc(unsigned CC)
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:410
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
Definition: MachineInstr.h:680
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
#define P(N)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
INITIALIZE_PASS_BEGIN(ARCBranchFinalize, "arc-branch-finalize", "ARC finalize branches", false, false) INITIALIZE_PASS_END(ARCBranchFinalize
static unsigned getBRccForPseudo(MachineInstr *MI)
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
Definition: FileCheck.cpp:215
FunctionPass * createARCBranchFinalizePass()
int64_t getImm() const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
objc arc
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:255
static unsigned getCmpForPseudo(MachineInstr *MI)
Representation of each machine instruction.
Definition: MachineInstr.h:63
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
Register getReg() const
getReg - Returns the register number.
#define LLVM_DEBUG(X)
Definition: Debug.h:122
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:415
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...