]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Hexagon/HexagonFixupHwLoops.cpp
Import CK as of 21d3e319407d19dece16ee317c757ffc54a452bc, which makes its
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Hexagon / HexagonFixupHwLoops.cpp
1 //===---- 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
9 // 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.
11 // This pass will identify and convert such LOOPn instructions to a proper
12 // form.
13 //===----------------------------------------------------------------------===//
14
15 #include "Hexagon.h"
16 #include "HexagonTargetMachine.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/Passes.h"
22 #include "llvm/CodeGen/TargetInstrInfo.h"
23 #include "llvm/PassSupport.h"
24
25 using namespace llvm;
26
27 static cl::opt<unsigned> MaxLoopRange(
28     "hexagon-loop-range", cl::Hidden, cl::init(200),
29     cl::desc("Restrict range of loopN instructions (testing only)"));
30
31 namespace llvm {
32   FunctionPass *createHexagonFixupHwLoops();
33   void initializeHexagonFixupHwLoopsPass(PassRegistry&);
34 }
35
36 namespace {
37   struct HexagonFixupHwLoops : public MachineFunctionPass {
38   public:
39     static char ID;
40
41     HexagonFixupHwLoops() : MachineFunctionPass(ID) {
42       initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
43     }
44
45     bool runOnMachineFunction(MachineFunction &MF) override;
46
47     MachineFunctionProperties getRequiredProperties() const override {
48       return MachineFunctionProperties().set(
49           MachineFunctionProperties::Property::NoVRegs);
50     }
51
52     StringRef getPassName() const override {
53       return "Hexagon Hardware Loop Fixup";
54     }
55
56     void getAnalysisUsage(AnalysisUsage &AU) const override {
57       AU.setPreservesCFG();
58       MachineFunctionPass::getAnalysisUsage(AU);
59     }
60
61   private:
62     /// \brief Check the offset between each loop instruction and
63     /// the loop basic block to determine if we can use the LOOP instruction
64     /// or if we need to set the LC/SA registers explicitly.
65     bool fixupLoopInstrs(MachineFunction &MF);
66
67     /// \brief Replace loop instruction with the constant extended
68     /// version if the loop label is too far from the loop instruction.
69     void useExtLoopInstr(MachineFunction &MF,
70                          MachineBasicBlock::iterator &MII);
71   };
72
73   char HexagonFixupHwLoops::ID = 0;
74 }
75
76 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
77                 "Hexagon Hardware Loops Fixup", false, false)
78
79 FunctionPass *llvm::createHexagonFixupHwLoops() {
80   return new HexagonFixupHwLoops();
81 }
82
83 /// \brief Returns true if the instruction is a hardware loop instruction.
84 static bool isHardwareLoop(const MachineInstr &MI) {
85   return MI.getOpcode() == Hexagon::J2_loop0r ||
86          MI.getOpcode() == Hexagon::J2_loop0i ||
87          MI.getOpcode() == Hexagon::J2_loop1r ||
88          MI.getOpcode() == Hexagon::J2_loop1i;
89 }
90
91 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
92   if (skipFunction(MF.getFunction()))
93     return false;
94   return fixupLoopInstrs(MF);
95 }
96
97 /// \brief For Hexagon, if the loop label is to far from the
98 /// loop instruction then we need to set the LC0 and SA0 registers
99 /// explicitly instead of using LOOP(start,count).  This function
100 /// checks the distance, and generates register assignments if needed.
101 ///
102 /// This function makes two passes over the basic blocks.  The first
103 /// pass computes the offset of the basic block from the start.
104 /// The second pass checks all the loop instructions.
105 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
106
107   // Offset of the current instruction from the start.
108   unsigned InstOffset = 0;
109   // Map for each basic block to it's first instruction.
110   DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset;
111
112   const HexagonInstrInfo *HII =
113       static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
114
115   // First pass - compute the offset of each basic block.
116   for (const MachineBasicBlock &MBB : MF) {
117     if (MBB.getAlignment()) {
118       // Although we don't know the exact layout of the final code, we need
119       // to account for alignment padding somehow. This heuristic pads each
120       // aligned basic block according to the alignment value.
121       int ByteAlign = (1u << MBB.getAlignment()) - 1;
122       InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign);
123     }
124
125     BlockToInstOffset[&MBB] = InstOffset;
126     for (const MachineInstr &MI : MBB)
127       InstOffset += HII->getSize(MI);
128   }
129
130   // Second pass - check each loop instruction to see if it needs to be
131   // converted.
132   bool Changed = false;
133   for (MachineBasicBlock &MBB : MF) {
134     InstOffset = BlockToInstOffset[&MBB];
135
136     // Loop over all the instructions.
137     MachineBasicBlock::iterator MII = MBB.begin();
138     MachineBasicBlock::iterator MIE = MBB.end();
139     while (MII != MIE) {
140       InstOffset += HII->getSize(*MII);
141       if (MII->isMetaInstruction()) {
142         ++MII;
143         continue;
144       }
145       if (isHardwareLoop(*MII)) {
146         assert(MII->getOperand(0).isMBB() &&
147                "Expect a basic block as loop operand");
148         int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
149         if ((unsigned)abs(diff) > MaxLoopRange) {
150           useExtLoopInstr(MF, MII);
151           MII = MBB.erase(MII);
152           Changed = true;
153         } else {
154           ++MII;
155         }
156       } else {
157         ++MII;
158       }
159     }
160   }
161
162   return Changed;
163 }
164
165 /// \brief Replace loop instructions with the constant extended version.
166 void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
167                                           MachineBasicBlock::iterator &MII) {
168   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
169   MachineBasicBlock *MBB = MII->getParent();
170   DebugLoc DL = MII->getDebugLoc();
171   MachineInstrBuilder MIB;
172   unsigned newOp;
173   switch (MII->getOpcode()) {
174   case Hexagon::J2_loop0r:
175     newOp = Hexagon::J2_loop0rext;
176     break;
177   case Hexagon::J2_loop0i:
178     newOp = Hexagon::J2_loop0iext;
179     break;
180   case Hexagon::J2_loop1r:
181     newOp = Hexagon::J2_loop1rext;
182     break;
183   case Hexagon::J2_loop1i:
184     newOp = Hexagon::J2_loop1iext;
185     break;
186   default:
187     llvm_unreachable("Invalid Hardware Loop Instruction.");
188   }
189   MIB = BuildMI(*MBB, MII, DL, TII->get(newOp));
190
191   for (unsigned i = 0; i < MII->getNumOperands(); ++i)
192     MIB.add(MII->getOperand(i));
193 }