blob: 91987a0d81fc40bea90cc80db31274fe7cce3eb6 [file] [log] [blame]
Brendon Cahoon31f87232012-05-11 19:56:59 +00001//===---- HexagonOptimizeConstExt.cpp - Optimize Constant Extender Use ----===//
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//===----------------------------------------------------------------------===//
9//
10// This pass traverses through all the basic blocks in a functions and replaces
11// constant extended instruction with their register equivalent if the same
12// constant is being used by more than two instructions.
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "xfer"
16#include "llvm/CodeGen/MachineDominators.h"
17#include "llvm/Support/Debug.h"
18#include "llvm/ADT/StringMap.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/SmallString.h"
21#include "llvm/ADT/Twine.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "HexagonTargetMachine.h"
24#include "HexagonConstExtInfo.h"
25#include "llvm/CodeGen/MachineFunctionAnalysis.h"
26#include "llvm/Support/CommandLine.h"
27#define DEBUG_TYPE "xfer"
28
29using namespace llvm;
30
31namespace {
32
33class HexagonOptimizeConstExt : public MachineFunctionPass {
34 HexagonTargetMachine& QTM;
35 const HexagonSubtarget &QST;
36
37public:
38 static char ID;
39 HexagonOptimizeConstExt(HexagonTargetMachine& TM)
40 : MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {}
41
42 const char *getPassName() const {
43 return "Remove sub-optimal uses of constant extenders";
44 }
45
46 void getAnalysisUsage(AnalysisUsage &AU) const {
47 MachineFunctionPass::getAnalysisUsage(AU);
48 AU.addRequired<MachineDominatorTree>();
49 AU.addPreserved<MachineDominatorTree>();
50 }
51
52 bool runOnMachineFunction(MachineFunction &Fn);
53 void removeConstExtFromMI (const HexagonInstrInfo *TII, MachineInstr* oldMI,
54 unsigned DestReg);
55};
56
57char HexagonOptimizeConstExt::ID = 0;
58
59// Remove constant extended instructions with the corresponding non-extended
60// instruction.
61void HexagonOptimizeConstExt::removeConstExtFromMI (const HexagonInstrInfo *TII,
62 MachineInstr* oldMI,
63 unsigned DestReg) {
64 assert(HexagonConstExt::NonExtEquivalentExists(oldMI->getOpcode()) &&
65 "Non-extended equivalent instruction doesn't exist");
66 MachineBasicBlock *MBB = oldMI->getParent ();
67 int oldOpCode = oldMI->getOpcode();
68 unsigned short CExtOpNum = HexagonConstExt::getCExtOpNum(oldOpCode);
69 unsigned numOperands = oldMI->getNumOperands();
70 MachineInstrBuilder MIB = BuildMI(*MBB, oldMI, oldMI->getDebugLoc(),
71 TII->get(HexagonConstExt::getNonExtOpcode(oldMI->getOpcode())));
72
73 for (unsigned i = 0; i < numOperands; ++i) {
74 if (i == CExtOpNum) {
75 MIB.addReg(DestReg);
76 if (oldMI->getDesc().mayLoad()) {
77 // As of now, only absolute addressing mode instructions can load from
78 // global addresses. Other addressing modes allow only constant
79 // literals. Load with absolute addressing mode gets replaced with the
80 // corresponding base+offset load.
81 if (oldMI->getOperand(i).isGlobal()) {
82 MIB.addImm(oldMI->getOperand(i).getOffset());
83 }
84 else
85 MIB.addImm(0);
86 }
87 else if (oldMI->getDesc().mayStore()){
88 if (oldMI->getOperand(i).isGlobal()) {
89 // If stored value is a global address and is extended, it is required
90 // to have 0 offset.
91 if (CExtOpNum == (numOperands-1))
92 assert((oldMI->getOperand(i).getOffset()==0) && "Invalid Offset");
93 else
94 MIB.addImm(oldMI->getOperand(i).getOffset());
95 }
96 else if (CExtOpNum != (numOperands-1))
97 MIB.addImm(0);
98 }
99 }
100 else {
101 const MachineOperand &op = oldMI->getOperand(i);
102 MIB.addOperand(op);
103 }
104 }
105 DEBUG(dbgs () << "Removing old instr: " << *oldMI << "\n");
106 DEBUG(dbgs() << "New instr: " << (*MIB) << "\n");
107 oldMI->eraseFromParent();
108}
109
110// Returns false for the following instructions, since it may not be profitable
111// to convert these instructions into a non-extended instruction if the offset
112// is non-zero.
113static bool canHaveAnyOffset(MachineInstr* MI) {
114 switch (MI->getOpcode()) {
115 case Hexagon::STriw_offset_ext_V4:
116 case Hexagon::STrih_offset_ext_V4:
117 return false;
118 default:
119 return true;
120 }
121}
122
123bool HexagonOptimizeConstExt::runOnMachineFunction(MachineFunction &Fn) {
124
125 const HexagonInstrInfo *TII = QTM.getInstrInfo();
126 MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
127
128 // CExtMap maintains a list of instructions for each constant extended value.
129 // It also keeps a flag for the value to indicate if it's a global address
130 // or a constant literal.
131 StringMap<std::pair<SmallVector<MachineInstr*, 8>, bool > > CExtMap;
132
133 // Loop over all the basic blocks
134 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
135 MBBb != MBBe; ++MBBb) {
136 MachineBasicBlock* MBB = MBBb;
137
138 // Traverse the basic block and update a map of (ImmValue->MI)
139 MachineBasicBlock::iterator MII = MBB->begin();
140 MachineBasicBlock::iterator MIE = MBB->end ();
141
142 while (MII != MIE) {
143 MachineInstr *MI = MII;
144 // Check if the instruction has any constant extended operand and also has
145 // a non-extended equivalent.
146 if (TII->isConstExtended(MI) &&
147 HexagonConstExt::NonExtEquivalentExists(MI->getOpcode())) {
148 short ExtOpNum = HexagonConstExt::getCExtOpNum(MI->getOpcode());
149 SmallString<256> TmpData;
150 if (MI->getOperand(ExtOpNum).isImm()) {
151 DEBUG(dbgs() << "Selected for replacement : " << *MI << "\n");
152 int ImmValue = MI->getOperand(ExtOpNum).getImm();
153 StringRef ExtValue = Twine(ImmValue).toStringRef(TmpData);
154 CExtMap[ExtValue].first.push_back(MI);
155 CExtMap[ExtValue].second = false;
156 }
157 else if (MI->getOperand(ExtOpNum).isGlobal()) {
158 StringRef ExtValue = MI->getOperand(ExtOpNum).getGlobal()->getName();
159 // If stored value is constant extended and has an offset, it's not
160 // profitable to replace these instructions with the non-extended
161 // version.
162 if (MI->getOperand(ExtOpNum).getOffset() == 0
163 || canHaveAnyOffset(MI)) {
164 DEBUG(dbgs() << "Selected for replacement : " << *MI << "\n");
165 CExtMap[ExtValue].first.push_back(MI);
166 CExtMap[ExtValue].second = true;
167 }
168 }
169 }
170 ++MII;
171 } // While ends
172 }
173
174 enum OpType {imm, GlobalAddr};
175 // Process the constants that have been extended.
176 for (StringMap<std::pair<SmallVector<MachineInstr*, 8>, bool> >::iterator II=
177 CExtMap.begin(), IE = CExtMap.end(); II != IE; ++II) {
178
179 SmallVector<MachineInstr*, 8> &MIList = (*II).second.first;
180
181 // Replace the constant extended instructions with the non-extended
182 // equivalent if more than 2 instructions extend the same constant value.
183 if (MIList.size() <= 2)
184 continue;
185
186 bool ExtOpType = (*II).second.second;
187 StringRef ExtValue = (*II).getKeyData();
188 const GlobalValue *GV = NULL;
189 unsigned char TargetFlags=0;
190 int ExtOpNum = HexagonConstExt::getCExtOpNum(MIList[0]->getOpcode());
191 SmallVector<MachineBasicBlock*, 8> MachineBlocks;
192
193 if (ExtOpType == GlobalAddr) {
194 GV = MIList[0]->getOperand(ExtOpNum).getGlobal();
195 TargetFlags = MIList[0]->getOperand(ExtOpNum).getTargetFlags();
196 }
197
198 // For each instruction in the list, record the block it belongs to.
199 for (SmallVector<MachineInstr*, 8>::iterator LB = MIList.begin(),
200 LE = MIList.end(); LB != LE; ++LB) {
201 MachineInstr *MI = (*LB);
202 MachineBlocks.push_back (MI->getParent());
203 }
204
205 MachineBasicBlock* CommDomBlock = MachineBlocks[0];
206 MachineBasicBlock* oldCommDomBlock = NULL;
207 // replaceMIs is the list of instructions to be replaced with a
208 // non-extended equivalent instruction.
209 // The idea here is that not all the instructions in the MIList will
210 // be replaced with a register.
211 SmallVector<MachineInstr*, 8> replaceMIs;
212 replaceMIs.push_back(MIList[0]);
213
214 for (unsigned i= 1; i < MachineBlocks.size(); ++i) {
215 oldCommDomBlock = CommDomBlock;
216 MachineBasicBlock *BB = MachineBlocks[i];
217 CommDomBlock = MDT.findNearestCommonDominator(&(*CommDomBlock),
218 &(*BB));
219 if (!CommDomBlock) {
220 CommDomBlock = oldCommDomBlock;
221 break;
222 }
223 replaceMIs.push_back(MIList[i]);
224 }
225
226 // Insert into CommDomBlock.
227 if (CommDomBlock) {
228 unsigned DestReg = TII->createVR (CommDomBlock->getParent(), MVT::i32);
229 MachineInstr *firstMI = CommDomBlock->getFirstNonPHI();
230 if (ExtOpType == imm) {
231 int ImmValue = 0;
232 ExtValue.getAsInteger(10,ImmValue);
233 BuildMI (*CommDomBlock, firstMI, firstMI->getDebugLoc(),
234 TII->get(Hexagon::TFRI), DestReg)
235 .addImm(ImmValue);
236 }
237 else {
238 BuildMI (*CommDomBlock, firstMI, firstMI->getDebugLoc(),
239 TII->get(Hexagon::TFRI_V4), DestReg)
240 .addGlobalAddress(GV, 0, TargetFlags);
241 }
242 for (unsigned i= 0; i < replaceMIs.size(); i++) {
243 MachineInstr *oldMI = replaceMIs[i];
244 removeConstExtFromMI(TII, oldMI, DestReg);
245 }
246 replaceMIs.clear();
247 }
248 }
249 return true;
250}
251}
252
253//===----------------------------------------------------------------------===//
254// Public Constructor Functions
255//===----------------------------------------------------------------------===//
256
257FunctionPass *
258llvm::createHexagonOptimizeConstExt(HexagonTargetMachine &TM) {
259 return new HexagonOptimizeConstExt(TM);
260}
261