blob: 11a455ce43470b04a188c230a6b0de6d3a84b588 [file] [log] [blame]
Eugene Zelenko3b873362017-09-28 22:27:31 +00001//===- HexagonCFGOptimizer.cpp - CFG optimizations ------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Tony Linthicum1213a7a2011-12-12 21:14:40 +00006//
7//===----------------------------------------------------------------------===//
8
Chandler Carruthed0881b2012-12-03 16:50:05 +00009#include "Hexagon.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000010#include "llvm/CodeGen/MachineBasicBlock.h"
11#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
12#include "llvm/CodeGen/MachineFunction.h"
Tony Linthicum1213a7a2011-12-12 21:14:40 +000013#include "llvm/CodeGen/MachineFunctionPass.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000014#include "llvm/CodeGen/MachineInstr.h"
15#include "llvm/CodeGen/MachineOperand.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000016#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000017#include "llvm/CodeGen/TargetSubtargetInfo.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000018#include "llvm/Pass.h"
19#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000020#include <cassert>
21#include <vector>
Tony Linthicum1213a7a2011-12-12 21:14:40 +000022
23using namespace llvm;
24
Chandler Carruth84e68b22014-04-22 02:41:26 +000025#define DEBUG_TYPE "hexagon_cfg"
26
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +000027namespace llvm {
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +000028
Eugene Zelenko3b873362017-09-28 22:27:31 +000029FunctionPass *createHexagonCFGOptimizer();
30void initializeHexagonCFGOptimizerPass(PassRegistry&);
31
32} // end namespace llvm
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +000033
Tony Linthicum1213a7a2011-12-12 21:14:40 +000034namespace {
35
36class HexagonCFGOptimizer : public MachineFunctionPass {
Tony Linthicum1213a7a2011-12-12 21:14:40 +000037private:
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +000038 void InvertAndChangeJumpTarget(MachineInstr &, MachineBasicBlock *);
Krzysztof Parzyszek0b3acbb2017-04-28 21:54:11 +000039 bool isOnFallThroughPath(MachineBasicBlock *MBB);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000040
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +000041public:
Tony Linthicum1213a7a2011-12-12 21:14:40 +000042 static char ID;
Eugene Zelenko3b873362017-09-28 22:27:31 +000043
Eric Christopher5c3376a2015-02-02 18:46:27 +000044 HexagonCFGOptimizer() : MachineFunctionPass(ID) {
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +000045 initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry());
46 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +000047
Mehdi Amini117296c2016-10-01 02:56:57 +000048 StringRef getPassName() const override { return "Hexagon CFG Optimizer"; }
Craig Topper906c2cd2014-04-29 07:58:16 +000049 bool runOnMachineFunction(MachineFunction &Fn) override;
Eugene Zelenko3b873362017-09-28 22:27:31 +000050
Derek Schuff1dbf7a52016-04-04 17:09:25 +000051 MachineFunctionProperties getRequiredProperties() const override {
52 return MachineFunctionProperties().set(
Matthias Braun1eb47362016-08-25 01:27:13 +000053 MachineFunctionProperties::Property::NoVRegs);
Derek Schuff1dbf7a52016-04-04 17:09:25 +000054 }
Tony Linthicum1213a7a2011-12-12 21:14:40 +000055};
56
Eugene Zelenko3b873362017-09-28 22:27:31 +000057} // end anonymous namespace
Tony Linthicum1213a7a2011-12-12 21:14:40 +000058
59char HexagonCFGOptimizer::ID = 0;
60
61static bool IsConditionalBranch(int Opc) {
Krzysztof Parzyszeka243adf2016-08-19 14:14:09 +000062 switch (Opc) {
63 case Hexagon::J2_jumpt:
64 case Hexagon::J2_jumptpt:
65 case Hexagon::J2_jumpf:
66 case Hexagon::J2_jumpfpt:
67 case Hexagon::J2_jumptnew:
68 case Hexagon::J2_jumpfnew:
69 case Hexagon::J2_jumptnewpt:
70 case Hexagon::J2_jumpfnewpt:
71 return true;
72 }
73 return false;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000074}
75
Tony Linthicum1213a7a2011-12-12 21:14:40 +000076static bool IsUnconditionalJump(int Opc) {
Colin LeMahieudb0b13c2014-12-10 21:24:10 +000077 return (Opc == Hexagon::J2_jump);
Tony Linthicum1213a7a2011-12-12 21:14:40 +000078}
79
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +000080void HexagonCFGOptimizer::InvertAndChangeJumpTarget(
81 MachineInstr &MI, MachineBasicBlock *NewTarget) {
Eric Christopher5c3376a2015-02-02 18:46:27 +000082 const TargetInstrInfo *TII =
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +000083 MI.getParent()->getParent()->getSubtarget().getInstrInfo();
Tony Linthicum1213a7a2011-12-12 21:14:40 +000084 int NewOpcode = 0;
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +000085 switch (MI.getOpcode()) {
Colin LeMahieudb0b13c2014-12-10 21:24:10 +000086 case Hexagon::J2_jumpt:
87 NewOpcode = Hexagon::J2_jumpf;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000088 break;
Colin LeMahieudb0b13c2014-12-10 21:24:10 +000089 case Hexagon::J2_jumpf:
90 NewOpcode = Hexagon::J2_jumpt;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000091 break;
Colin LeMahieudb0b13c2014-12-10 21:24:10 +000092 case Hexagon::J2_jumptnewpt:
93 NewOpcode = Hexagon::J2_jumpfnewpt;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000094 break;
Colin LeMahieudb0b13c2014-12-10 21:24:10 +000095 case Hexagon::J2_jumpfnewpt:
96 NewOpcode = Hexagon::J2_jumptnewpt;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000097 break;
Tony Linthicum1213a7a2011-12-12 21:14:40 +000098 default:
Craig Toppere55c5562012-02-07 02:50:20 +000099 llvm_unreachable("Cannot handle this case");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000100 }
101
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000102 MI.setDesc(TII->get(NewOpcode));
103 MI.getOperand(1).setMBB(NewTarget);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000104}
105
Krzysztof Parzyszek0b3acbb2017-04-28 21:54:11 +0000106bool HexagonCFGOptimizer::isOnFallThroughPath(MachineBasicBlock *MBB) {
107 if (MBB->canFallThrough())
108 return true;
109 for (MachineBasicBlock *PB : MBB->predecessors())
110 if (PB->isLayoutSuccessor(MBB) && PB->canFallThrough())
111 return true;
112 return false;
113}
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000114
115bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) {
Matthias Braunf1caa282017-12-15 22:22:58 +0000116 if (skipFunction(Fn.getFunction()))
Andrew Kaylor5b444a22016-04-26 19:46:28 +0000117 return false;
118
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000119 // Loop over all of the basic blocks.
120 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
121 MBBb != MBBe; ++MBBb) {
Duncan P. N. Exon Smitha72c6e22015-10-20 00:46:39 +0000122 MachineBasicBlock *MBB = &*MBBb;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000123
124 // Traverse the basic block.
125 MachineBasicBlock::iterator MII = MBB->getFirstTerminator();
126 if (MII != MBB->end()) {
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000127 MachineInstr &MI = *MII;
128 int Opc = MI.getOpcode();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000129 if (IsConditionalBranch(Opc)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000130 // (Case 1) Transform the code if the following condition occurs:
131 // BB1: if (p0) jump BB3
132 // ...falls-through to BB2 ...
133 // BB2: jump BB4
134 // ...next block in layout is BB3...
135 // BB3: ...
136 //
137 // Transform this to:
138 // BB1: if (!p0) jump BB4
139 // Remove BB2
140 // BB3: ...
141 //
142 // (Case 2) A variation occurs when BB3 contains a JMP to BB4:
143 // BB1: if (p0) jump BB3
144 // ...falls-through to BB2 ...
145 // BB2: jump BB4
146 // ...other basic blocks ...
147 // BB4:
148 // ...not a fall-thru
149 // BB3: ...
150 // jump BB4
151 //
152 // Transform this to:
153 // BB1: if (!p0) jump BB4
154 // Remove BB2
155 // BB3: ...
156 // BB4: ...
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000157 unsigned NumSuccs = MBB->succ_size();
158 MachineBasicBlock::succ_iterator SI = MBB->succ_begin();
159 MachineBasicBlock* FirstSucc = *SI;
160 MachineBasicBlock* SecondSucc = *(++SI);
Craig Topper062a2ba2014-04-25 05:30:21 +0000161 MachineBasicBlock* LayoutSucc = nullptr;
162 MachineBasicBlock* JumpAroundTarget = nullptr;
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000163
164 if (MBB->isLayoutSuccessor(FirstSucc)) {
165 LayoutSucc = FirstSucc;
166 JumpAroundTarget = SecondSucc;
167 } else if (MBB->isLayoutSuccessor(SecondSucc)) {
168 LayoutSucc = SecondSucc;
169 JumpAroundTarget = FirstSucc;
170 } else {
171 // Odd case...cannot handle.
172 }
173
174 // The target of the unconditional branch must be JumpAroundTarget.
175 // TODO: If not, we should not invert the unconditional branch.
Craig Topper062a2ba2014-04-25 05:30:21 +0000176 MachineBasicBlock* CondBranchTarget = nullptr;
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000177 if (MI.getOpcode() == Hexagon::J2_jumpt ||
178 MI.getOpcode() == Hexagon::J2_jumpf) {
179 CondBranchTarget = MI.getOperand(1).getMBB();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000180 }
181
182 if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) {
183 continue;
184 }
185
186 if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) {
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000187 // Ensure that BB2 has one instruction -- an unconditional jump.
188 if ((LayoutSucc->size() == 1) &&
189 IsUnconditionalJump(LayoutSucc->front().getOpcode())) {
Krzysztof Parzyszek89757432016-05-05 22:00:44 +0000190 assert(JumpAroundTarget && "jump target is needed to process second basic block");
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000191 MachineBasicBlock* UncondTarget =
192 LayoutSucc->front().getOperand(0).getMBB();
193 // Check if the layout successor of BB2 is BB3.
194 bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget);
195 bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) &&
Eugene Zelenko3b873362017-09-28 22:27:31 +0000196 !JumpAroundTarget->empty() &&
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000197 IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) &&
198 JumpAroundTarget->pred_size() == 1 &&
199 JumpAroundTarget->succ_size() == 1;
200
201 if (case1 || case2) {
202 InvertAndChangeJumpTarget(MI, UncondTarget);
Cong Houd97c1002015-12-01 05:29:22 +0000203 MBB->replaceSuccessor(JumpAroundTarget, UncondTarget);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000204
205 // Remove the unconditional branch in LayoutSucc.
206 LayoutSucc->erase(LayoutSucc->begin());
Cong Houd97c1002015-12-01 05:29:22 +0000207 LayoutSucc->replaceSuccessor(UncondTarget, JumpAroundTarget);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000208
209 // This code performs the conversion for case 2, which moves
210 // the block to the fall-thru case (BB3 in the code above).
211 if (case2 && !case1) {
212 JumpAroundTarget->moveAfter(LayoutSucc);
213 // only move a block if it doesn't have a fall-thru. otherwise
214 // the CFG will be incorrect.
Krzysztof Parzyszek0b3acbb2017-04-28 21:54:11 +0000215 if (!isOnFallThroughPath(UncondTarget))
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000216 UncondTarget->moveAfter(JumpAroundTarget);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000217 }
218
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000219 // Correct live-in information. Is used by post-RA scheduler
220 // The live-in to LayoutSucc is now all values live-in to
221 // JumpAroundTarget.
Matthias Braund9da1622015-09-09 18:08:03 +0000222 std::vector<MachineBasicBlock::RegisterMaskPair> OrigLiveIn(
223 LayoutSucc->livein_begin(), LayoutSucc->livein_end());
224 std::vector<MachineBasicBlock::RegisterMaskPair> NewLiveIn(
225 JumpAroundTarget->livein_begin(),
226 JumpAroundTarget->livein_end());
227 for (const auto &OrigLI : OrigLiveIn)
228 LayoutSucc->removeLiveIn(OrigLI.PhysReg);
229 for (const auto &NewLI : NewLiveIn)
230 LayoutSucc->addLiveIn(NewLI);
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000231 }
232 }
233 }
234 }
235 }
236 }
237 return true;
238}
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000239
240//===----------------------------------------------------------------------===//
241// Public Constructor Functions
242//===----------------------------------------------------------------------===//
243
Chandler Carruthd4741442016-06-03 10:13:29 +0000244INITIALIZE_PASS(HexagonCFGOptimizer, "hexagon-cfg", "Hexagon CFG Optimizer",
245 false, false)
Krzysztof Parzyszek18ee1192013-05-06 21:58:00 +0000246
Eric Christopher5c3376a2015-02-02 18:46:27 +0000247FunctionPass *llvm::createHexagonCFGOptimizer() {
248 return new HexagonCFGOptimizer();
Tony Linthicum1213a7a2011-12-12 21:14:40 +0000249}