blob: dfd1f1d4f886b51d9f34074a56bf9157b64a4240 [file] [log] [blame]
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +00001//===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8// The loop start address in the LOOPn instruction is encoded as a distance
Brendon Cahoon55bdeb72015-04-27 14:16:43 +00009// from the LOOPn instruction itself. If the start address is too far from
10// the LOOPn instruction, the instruction needs to use a constant extender.
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000011// This pass will identify and convert such LOOPn instructions to a proper
12// form.
13//===----------------------------------------------------------------------===//
14
15
16#include "llvm/ADT/DenseMap.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000017#include "Hexagon.h"
18#include "HexagonTargetMachine.h"
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000019#include "llvm/CodeGen/MachineFunction.h"
20#include "llvm/CodeGen/MachineFunctionPass.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/Passes.h"
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000023#include "llvm/PassSupport.h"
24#include "llvm/Target/TargetInstrInfo.h"
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000025
26using namespace llvm;
27
Brendon Cahoon55bdeb72015-04-27 14:16:43 +000028static cl::opt<unsigned> MaxLoopRange(
29 "hexagon-loop-range", cl::Hidden, cl::init(200),
30 cl::desc("Restrict range of loopN instructions (testing only)"));
31
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000032namespace llvm {
Colin LeMahieu56efafc2015-06-15 19:05:35 +000033 FunctionPass *createHexagonFixupHwLoops();
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000034 void initializeHexagonFixupHwLoopsPass(PassRegistry&);
35}
36
37namespace {
38 struct HexagonFixupHwLoops : public MachineFunctionPass {
39 public:
40 static char ID;
41
42 HexagonFixupHwLoops() : MachineFunctionPass(ID) {
43 initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
44 }
45
Craig Topper906c2cd2014-04-29 07:58:16 +000046 bool runOnMachineFunction(MachineFunction &MF) override;
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000047
Derek Schuff1dbf7a52016-04-04 17:09:25 +000048 MachineFunctionProperties getRequiredProperties() const override {
49 return MachineFunctionProperties().set(
Matthias Braun1eb47362016-08-25 01:27:13 +000050 MachineFunctionProperties::Property::NoVRegs);
Derek Schuff1dbf7a52016-04-04 17:09:25 +000051 }
52
Mehdi Amini117296c2016-10-01 02:56:57 +000053 StringRef getPassName() const override {
Craig Topper906c2cd2014-04-29 07:58:16 +000054 return "Hexagon Hardware Loop Fixup";
55 }
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000056
Craig Topper906c2cd2014-04-29 07:58:16 +000057 void getAnalysisUsage(AnalysisUsage &AU) const override {
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000058 AU.setPreservesCFG();
59 MachineFunctionPass::getAnalysisUsage(AU);
60 }
61
62 private:
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000063 /// \brief Check the offset between each loop instruction and
64 /// the loop basic block to determine if we can use the LOOP instruction
65 /// or if we need to set the LC/SA registers explicitly.
66 bool fixupLoopInstrs(MachineFunction &MF);
67
Brendon Cahoon55bdeb72015-04-27 14:16:43 +000068 /// \brief Replace loop instruction with the constant extended
69 /// version if the loop label is too far from the loop instruction.
70 void useExtLoopInstr(MachineFunction &MF,
71 MachineBasicBlock::iterator &MII);
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000072 };
73
74 char HexagonFixupHwLoops::ID = 0;
Alexander Kornienkof00654e2015-06-23 09:49:53 +000075}
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000076
77INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
78 "Hexagon Hardware Loops Fixup", false, false)
79
80FunctionPass *llvm::createHexagonFixupHwLoops() {
81 return new HexagonFixupHwLoops();
82}
83
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000084/// \brief Returns true if the instruction is a hardware loop instruction.
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +000085static bool isHardwareLoop(const MachineInstr &MI) {
86 return MI.getOpcode() == Hexagon::J2_loop0r ||
87 MI.getOpcode() == Hexagon::J2_loop0i ||
88 MI.getOpcode() == Hexagon::J2_loop1r ||
89 MI.getOpcode() == Hexagon::J2_loop1i;
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000090}
91
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000092bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
Andrew Kaylor5b444a22016-04-26 19:46:28 +000093 if (skipFunction(*MF.getFunction()))
94 return false;
Brendon Cahoon55bdeb72015-04-27 14:16:43 +000095 return fixupLoopInstrs(MF);
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000096}
97
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +000098/// \brief For Hexagon, if the loop label is to far from the
99/// loop instruction then we need to set the LC0 and SA0 registers
100/// explicitly instead of using LOOP(start,count). This function
101/// checks the distance, and generates register assignments if needed.
102///
103/// This function makes two passes over the basic blocks. The first
104/// pass computes the offset of the basic block from the start.
105/// The second pass checks all the loop instructions.
106bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
107
108 // Offset of the current instruction from the start.
109 unsigned InstOffset = 0;
110 // Map for each basic block to it's first instruction.
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000111 DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset;
112
113 const HexagonInstrInfo *HII =
114 static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000115
116 // First pass - compute the offset of each basic block.
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000117 for (const MachineBasicBlock &MBB : MF) {
118 if (MBB.getAlignment()) {
119 // Although we don't know the exact layout of the final code, we need
120 // to account for alignment padding somehow. This heuristic pads each
121 // aligned basic block according to the alignment value.
122 int ByteAlign = (1u << MBB.getAlignment()) - 1;
123 InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign);
124 }
125
126 BlockToInstOffset[&MBB] = InstOffset;
127 for (const MachineInstr &MI : MBB)
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000128 InstOffset += HII->getSize(MI);
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000129 }
130
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000131 // Second pass - check each loop instruction to see if it needs to be
132 // converted.
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000133 bool Changed = false;
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000134 for (MachineBasicBlock &MBB : MF) {
135 InstOffset = BlockToInstOffset[&MBB];
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000136
137 // Loop over all the instructions.
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000138 MachineBasicBlock::iterator MII = MBB.begin();
139 MachineBasicBlock::iterator MIE = MBB.end();
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000140 while (MII != MIE) {
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000141 InstOffset += HII->getSize(*MII);
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000142 if (MII->isDebugValue()) {
143 ++MII;
144 continue;
145 }
Duncan P. N. Exon Smith98226e32016-07-12 01:55:32 +0000146 if (isHardwareLoop(*MII)) {
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000147 assert(MII->getOperand(0).isMBB() &&
148 "Expect a basic block as loop operand");
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000149 int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
150 if ((unsigned)abs(diff) > MaxLoopRange) {
151 useExtLoopInstr(MF, MII);
152 MII = MBB.erase(MII);
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000153 Changed = true;
154 } else {
155 ++MII;
156 }
157 } else {
158 ++MII;
159 }
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000160 }
161 }
162
163 return Changed;
164}
165
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000166/// \brief Replace loop instructions with the constant extended version.
167void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
168 MachineBasicBlock::iterator &MII) {
Eric Christopherfc6de422014-08-05 02:39:49 +0000169 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000170 MachineBasicBlock *MBB = MII->getParent();
171 DebugLoc DL = MII->getDebugLoc();
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000172 MachineInstrBuilder MIB;
173 unsigned newOp;
174 switch (MII->getOpcode()) {
175 case Hexagon::J2_loop0r:
176 newOp = Hexagon::J2_loop0rext;
177 break;
178 case Hexagon::J2_loop0i:
179 newOp = Hexagon::J2_loop0iext;
180 break;
181 case Hexagon::J2_loop1r:
182 newOp = Hexagon::J2_loop1rext;
183 break;
184 case Hexagon::J2_loop1i:
185 newOp = Hexagon::J2_loop1iext;
186 break;
187 default:
188 llvm_unreachable("Invalid Hardware Loop Instruction.");
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000189 }
Brendon Cahoon55bdeb72015-04-27 14:16:43 +0000190 MIB = BuildMI(*MBB, MII, DL, TII->get(newOp));
191
192 for (unsigned i = 0; i < MII->getNumOperands(); ++i)
193 MIB.addOperand(MII->getOperand(i));
Krzysztof Parzyszek9a278f12013-02-11 21:37:55 +0000194}