File: | lib/Target/Hexagon/HexagonFixupHwLoops.cpp |
Location: | line 131, column 3 |
Description: | Value stored to 'InstOffset' is never read |
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 | |
16 | #include "llvm/ADT/DenseMap.h" |
17 | #include "Hexagon.h" |
18 | #include "HexagonTargetMachine.h" |
19 | #include "llvm/CodeGen/MachineFunction.h" |
20 | #include "llvm/CodeGen/MachineFunctionPass.h" |
21 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
22 | #include "llvm/CodeGen/Passes.h" |
23 | #include "llvm/PassSupport.h" |
24 | #include "llvm/Target/TargetInstrInfo.h" |
25 | |
26 | using namespace llvm; |
27 | |
28 | static cl::opt<unsigned> MaxLoopRange( |
29 | "hexagon-loop-range", cl::Hidden, cl::init(200), |
30 | cl::desc("Restrict range of loopN instructions (testing only)")); |
31 | |
32 | namespace llvm { |
33 | FunctionPass *createHexagonFixupHwLoops(); |
34 | void initializeHexagonFixupHwLoopsPass(PassRegistry&); |
35 | } |
36 | |
37 | namespace { |
38 | struct HexagonFixupHwLoops : public MachineFunctionPass { |
39 | public: |
40 | static char ID; |
41 | |
42 | HexagonFixupHwLoops() : MachineFunctionPass(ID) { |
43 | initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry()); |
44 | } |
45 | |
46 | bool runOnMachineFunction(MachineFunction &MF) override; |
47 | |
48 | MachineFunctionProperties getRequiredProperties() const override { |
49 | return MachineFunctionProperties().set( |
50 | MachineFunctionProperties::Property::AllVRegsAllocated); |
51 | } |
52 | |
53 | const char *getPassName() const override { |
54 | return "Hexagon Hardware Loop Fixup"; |
55 | } |
56 | |
57 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
58 | AU.setPreservesCFG(); |
59 | MachineFunctionPass::getAnalysisUsage(AU); |
60 | } |
61 | |
62 | private: |
63 | /// \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 | |
68 | /// \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); |
72 | }; |
73 | |
74 | char HexagonFixupHwLoops::ID = 0; |
75 | } |
76 | |
77 | INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",static void* initializeHexagonFixupHwLoopsPassOnce(PassRegistry &Registry) { PassInfo *PI = new PassInfo("Hexagon Hardware Loops Fixup" , "hwloopsfixup", & HexagonFixupHwLoops ::ID, PassInfo::NormalCtor_t (callDefaultCtor< HexagonFixupHwLoops >), false, false) ; Registry.registerPass(*PI, true); return PI; } void llvm::initializeHexagonFixupHwLoopsPass (PassRegistry &Registry) { static volatile sys::cas_flag initialized = 0; sys::cas_flag old_val = sys::CompareAndSwap(&initialized , 1, 0); if (old_val == 0) { initializeHexagonFixupHwLoopsPassOnce (Registry); sys::MemoryFence(); ; ; initialized = 2; ; } else { sys::cas_flag tmp = initialized; sys::MemoryFence(); while (tmp != 2) { tmp = initialized; sys::MemoryFence(); } } ; } |
78 | "Hexagon Hardware Loops Fixup", false, false)static void* initializeHexagonFixupHwLoopsPassOnce(PassRegistry &Registry) { PassInfo *PI = new PassInfo("Hexagon Hardware Loops Fixup" , "hwloopsfixup", & HexagonFixupHwLoops ::ID, PassInfo::NormalCtor_t (callDefaultCtor< HexagonFixupHwLoops >), false, false) ; Registry.registerPass(*PI, true); return PI; } void llvm::initializeHexagonFixupHwLoopsPass (PassRegistry &Registry) { static volatile sys::cas_flag initialized = 0; sys::cas_flag old_val = sys::CompareAndSwap(&initialized , 1, 0); if (old_val == 0) { initializeHexagonFixupHwLoopsPassOnce (Registry); sys::MemoryFence(); ; ; initialized = 2; ; } else { sys::cas_flag tmp = initialized; sys::MemoryFence(); while (tmp != 2) { tmp = initialized; sys::MemoryFence(); } } ; } |
79 | |
80 | FunctionPass *llvm::createHexagonFixupHwLoops() { |
81 | return new HexagonFixupHwLoops(); |
82 | } |
83 | |
84 | /// \brief Returns true if the instruction is a hardware loop instruction. |
85 | static 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; |
90 | } |
91 | |
92 | bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) { |
93 | return fixupLoopInstrs(MF); |
94 | } |
95 | |
96 | /// \brief For Hexagon, if the loop label is to far from the |
97 | /// loop instruction then we need to set the LC0 and SA0 registers |
98 | /// explicitly instead of using LOOP(start,count). This function |
99 | /// checks the distance, and generates register assignments if needed. |
100 | /// |
101 | /// This function makes two passes over the basic blocks. The first |
102 | /// pass computes the offset of the basic block from the start. |
103 | /// The second pass checks all the loop instructions. |
104 | bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { |
105 | |
106 | // Offset of the current instruction from the start. |
107 | unsigned InstOffset = 0; |
108 | // Map for each basic block to it's first instruction. |
109 | DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset; |
110 | |
111 | const HexagonInstrInfo *HII = |
112 | static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); |
113 | |
114 | // First pass - compute the offset of each basic block. |
115 | for (const MachineBasicBlock &MBB : MF) { |
116 | if (MBB.getAlignment()) { |
117 | // Although we don't know the exact layout of the final code, we need |
118 | // to account for alignment padding somehow. This heuristic pads each |
119 | // aligned basic block according to the alignment value. |
120 | int ByteAlign = (1u << MBB.getAlignment()) - 1; |
121 | InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign); |
122 | } |
123 | |
124 | BlockToInstOffset[&MBB] = InstOffset; |
125 | for (const MachineInstr &MI : MBB) |
126 | InstOffset += HII->getSize(&MI); |
127 | } |
128 | |
129 | // Second pass - check each loop instruction to see if it needs to be |
130 | // converted. |
131 | InstOffset = 0; |
Value stored to 'InstOffset' is never read | |
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->isDebugValue()) { |
142 | ++MII; |
143 | continue; |
144 | } |
145 | if (isHardwareLoop(MII)) { |
146 | assert(MII->getOperand(0).isMBB() &&((MII->getOperand(0).isMBB() && "Expect a basic block as loop operand" ) ? static_cast<void> (0) : __assert_fail ("MII->getOperand(0).isMBB() && \"Expect a basic block as loop operand\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.9~svn267387/lib/Target/Hexagon/HexagonFixupHwLoops.cpp" , 147, __PRETTY_FUNCTION__)) |
147 | "Expect a basic block as loop operand")((MII->getOperand(0).isMBB() && "Expect a basic block as loop operand" ) ? static_cast<void> (0) : __assert_fail ("MII->getOperand(0).isMBB() && \"Expect a basic block as loop operand\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.9~svn267387/lib/Target/Hexagon/HexagonFixupHwLoops.cpp" , 147, __PRETTY_FUNCTION__)); |
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.")::llvm::llvm_unreachable_internal("Invalid Hardware Loop Instruction." , "/tmp/buildd/llvm-toolchain-snapshot-3.9~svn267387/lib/Target/Hexagon/HexagonFixupHwLoops.cpp" , 187); |
188 | } |
189 | MIB = BuildMI(*MBB, MII, DL, TII->get(newOp)); |
190 | |
191 | for (unsigned i = 0; i < MII->getNumOperands(); ++i) |
192 | MIB.addOperand(MII->getOperand(i)); |
193 | } |