LLVM  3.7.0
HexagonCFGOptimizer.cpp
Go to the documentation of this file.
1 //===-- HexagonCFGOptimizer.cpp - CFG optimizations -----------------------===//
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Hexagon.h"
11 #include "HexagonSubtarget.h"
12 #include "HexagonTargetMachine.h"
18 #include "llvm/CodeGen/Passes.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/Debug.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "hexagon_cfg"
29 
30 namespace llvm {
33 }
34 
35 
36 namespace {
37 
38 class HexagonCFGOptimizer : public MachineFunctionPass {
39 
40 private:
41  void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*);
42 
43  public:
44  static char ID;
45  HexagonCFGOptimizer() : MachineFunctionPass(ID) {
47  }
48 
49  const char *getPassName() const override {
50  return "Hexagon CFG Optimizer";
51  }
52  bool runOnMachineFunction(MachineFunction &Fn) override;
53 };
54 
55 
57 
58 static bool IsConditionalBranch(int Opc) {
59  return (Opc == Hexagon::J2_jumpt) || (Opc == Hexagon::J2_jumpf)
60  || (Opc == Hexagon::J2_jumptnewpt) || (Opc == Hexagon::J2_jumpfnewpt);
61 }
62 
63 
64 static bool IsUnconditionalJump(int Opc) {
65  return (Opc == Hexagon::J2_jump);
66 }
67 
68 
69 void
70 HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI,
71  MachineBasicBlock* NewTarget) {
72  const TargetInstrInfo *TII =
74  int NewOpcode = 0;
75  switch(MI->getOpcode()) {
76  case Hexagon::J2_jumpt:
77  NewOpcode = Hexagon::J2_jumpf;
78  break;
79 
80  case Hexagon::J2_jumpf:
81  NewOpcode = Hexagon::J2_jumpt;
82  break;
83 
84  case Hexagon::J2_jumptnewpt:
85  NewOpcode = Hexagon::J2_jumpfnewpt;
86  break;
87 
88  case Hexagon::J2_jumpfnewpt:
89  NewOpcode = Hexagon::J2_jumptnewpt;
90  break;
91 
92  default:
93  llvm_unreachable("Cannot handle this case");
94  }
95 
96  MI->setDesc(TII->get(NewOpcode));
97  MI->getOperand(1).setMBB(NewTarget);
98 }
99 
100 
101 bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) {
102  // Loop over all of the basic blocks.
103  for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
104  MBBb != MBBe; ++MBBb) {
105  MachineBasicBlock* MBB = MBBb;
106 
107  // Traverse the basic block.
109  if (MII != MBB->end()) {
110  MachineInstr *MI = MII;
111  int Opc = MI->getOpcode();
112  if (IsConditionalBranch(Opc)) {
113 
114  //
115  // (Case 1) Transform the code if the following condition occurs:
116  // BB1: if (p0) jump BB3
117  // ...falls-through to BB2 ...
118  // BB2: jump BB4
119  // ...next block in layout is BB3...
120  // BB3: ...
121  //
122  // Transform this to:
123  // BB1: if (!p0) jump BB4
124  // Remove BB2
125  // BB3: ...
126  //
127  // (Case 2) A variation occurs when BB3 contains a JMP to BB4:
128  // BB1: if (p0) jump BB3
129  // ...falls-through to BB2 ...
130  // BB2: jump BB4
131  // ...other basic blocks ...
132  // BB4:
133  // ...not a fall-thru
134  // BB3: ...
135  // jump BB4
136  //
137  // Transform this to:
138  // BB1: if (!p0) jump BB4
139  // Remove BB2
140  // BB3: ...
141  // BB4: ...
142  //
143  unsigned NumSuccs = MBB->succ_size();
145  MachineBasicBlock* FirstSucc = *SI;
146  MachineBasicBlock* SecondSucc = *(++SI);
147  MachineBasicBlock* LayoutSucc = nullptr;
148  MachineBasicBlock* JumpAroundTarget = nullptr;
149 
150  if (MBB->isLayoutSuccessor(FirstSucc)) {
151  LayoutSucc = FirstSucc;
152  JumpAroundTarget = SecondSucc;
153  } else if (MBB->isLayoutSuccessor(SecondSucc)) {
154  LayoutSucc = SecondSucc;
155  JumpAroundTarget = FirstSucc;
156  } else {
157  // Odd case...cannot handle.
158  }
159 
160  // The target of the unconditional branch must be JumpAroundTarget.
161  // TODO: If not, we should not invert the unconditional branch.
162  MachineBasicBlock* CondBranchTarget = nullptr;
163  if ((MI->getOpcode() == Hexagon::J2_jumpt) ||
164  (MI->getOpcode() == Hexagon::J2_jumpf)) {
165  CondBranchTarget = MI->getOperand(1).getMBB();
166  }
167 
168  if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) {
169  continue;
170  }
171 
172  if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) {
173 
174  // Ensure that BB2 has one instruction -- an unconditional jump.
175  if ((LayoutSucc->size() == 1) &&
176  IsUnconditionalJump(LayoutSucc->front().getOpcode())) {
177  MachineBasicBlock* UncondTarget =
178  LayoutSucc->front().getOperand(0).getMBB();
179  // Check if the layout successor of BB2 is BB3.
180  bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget);
181  bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) &&
182  JumpAroundTarget->size() >= 1 &&
183  IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) &&
184  JumpAroundTarget->pred_size() == 1 &&
185  JumpAroundTarget->succ_size() == 1;
186 
187  if (case1 || case2) {
188  InvertAndChangeJumpTarget(MI, UncondTarget);
189  MBB->removeSuccessor(JumpAroundTarget);
190  MBB->addSuccessor(UncondTarget);
191 
192  // Remove the unconditional branch in LayoutSucc.
193  LayoutSucc->erase(LayoutSucc->begin());
194  LayoutSucc->removeSuccessor(UncondTarget);
195  LayoutSucc->addSuccessor(JumpAroundTarget);
196 
197  // This code performs the conversion for case 2, which moves
198  // the block to the fall-thru case (BB3 in the code above).
199  if (case2 && !case1) {
200  JumpAroundTarget->moveAfter(LayoutSucc);
201  // only move a block if it doesn't have a fall-thru. otherwise
202  // the CFG will be incorrect.
203  if (!UncondTarget->canFallThrough()) {
204  UncondTarget->moveAfter(JumpAroundTarget);
205  }
206  }
207 
208  //
209  // Correct live-in information. Is used by post-RA scheduler
210  // The live-in to LayoutSucc is now all values live-in to
211  // JumpAroundTarget.
212  //
213  std::vector<unsigned> OrigLiveIn(LayoutSucc->livein_begin(),
214  LayoutSucc->livein_end());
215  std::vector<unsigned> NewLiveIn(JumpAroundTarget->livein_begin(),
216  JumpAroundTarget->livein_end());
217  for (unsigned i = 0; i < OrigLiveIn.size(); ++i) {
218  LayoutSucc->removeLiveIn(OrigLiveIn[i]);
219  }
220  for (unsigned i = 0; i < NewLiveIn.size(); ++i) {
221  LayoutSucc->addLiveIn(NewLiveIn[i]);
222  }
223  }
224  }
225  }
226  }
227  }
228  }
229  return true;
230 }
231 }
232 
233 
234 //===----------------------------------------------------------------------===//
235 // Public Constructor Functions
236 //===----------------------------------------------------------------------===//
237 
239  PassInfo *PI = new PassInfo("Hexagon CFG Optimizer", "hexagon-cfg",
240  &HexagonCFGOptimizer::ID, nullptr, false, false);
241  Registry.registerPass(*PI, true);
242 }
243 
246 }
247 
249  return new HexagonCFGOptimizer();
250 }
unsigned succ_size() const
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
MachineBasicBlock * getMBB() const
iterator getFirstTerminator()
getFirstTerminator - returns an iterator to the first terminator instruction of this basic block...
A global registry used in conjunction with static constructors to make pluggable components (like tar...
Definition: Registry.h:61
void removeLiveIn(unsigned Reg)
removeLiveIn - Remove the specified register from the live in set.
void addLiveIn(unsigned Reg)
Adds the specified register as a live in.
void moveAfter(MachineBasicBlock *NewBefore)
livein_iterator livein_begin() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
std::vector< MachineBasicBlock * >::iterator succ_iterator
bool canFallThrough()
canFallThrough - Return true if the block can implicitly transfer control to the block after it by fa...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:120
TargetInstrInfo - Interface to description of machine instruction set.
bundle_iterator< MachineInstr, instr_iterator > iterator
livein_iterator livein_end() const
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:273
static void initializePassOnce(PassRegistry &Registry)
void setMBB(MachineBasicBlock *MBB)
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
PassInfo class - An instance of this class exists for every pass known by the system, and can be obtained from a live Pass by calling its getPassInfo() method.
Definition: PassInfo.h:30
void removeSuccessor(MachineBasicBlock *succ)
removeSuccessor - Remove successor from the successors list of this MachineBasicBlock.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
bool isSuccessor(const MachineBasicBlock *MBB) const
isSuccessor - Return true if the specified MBB is a successor of this block.
Representation of each machine instruction.
Definition: MachineInstr.h:51
virtual const TargetInstrInfo * getInstrInfo() const
#define CALL_ONCE_INITIALIZATION(function)
Definition: PassSupport.h:36
void initializeHexagonCFGOptimizerPass(PassRegistry &)
BasicBlockListType::iterator iterator
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:41
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
isLayoutSuccessor - Return true if the specified MBB will be emitted immediately after this block...
void registerPass(const PassInfo &PI, bool ShouldFree=false)
registerPass - Register a pass (by means of its PassInfo) with the registry.
void addSuccessor(MachineBasicBlock *succ, uint32_t weight=0)
addSuccessor - Add succ as a successor of this MachineBasicBlock.
unsigned pred_size() const
FunctionPass * createHexagonCFGOptimizer()