Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- HexagonOptAddrMode.cpp ---------------------------------------------===//
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
// This implements a Hexagon-specific pass to optimize addressing mode for
10
// load/store instructions.
11
//===----------------------------------------------------------------------===//
12
13
#include "HexagonInstrInfo.h"
14
#include "HexagonSubtarget.h"
15
#include "MCTargetDesc/HexagonBaseInfo.h"
16
#include "RDFGraph.h"
17
#include "RDFLiveness.h"
18
#include "RDFRegisters.h"
19
#include "llvm/ADT/DenseMap.h"
20
#include "llvm/ADT/DenseSet.h"
21
#include "llvm/ADT/StringRef.h"
22
#include "llvm/CodeGen/MachineBasicBlock.h"
23
#include "llvm/CodeGen/MachineDominanceFrontier.h"
24
#include "llvm/CodeGen/MachineDominators.h"
25
#include "llvm/CodeGen/MachineFunction.h"
26
#include "llvm/CodeGen/MachineFunctionPass.h"
27
#include "llvm/CodeGen/MachineInstr.h"
28
#include "llvm/CodeGen/MachineInstrBuilder.h"
29
#include "llvm/CodeGen/MachineOperand.h"
30
#include "llvm/MC/MCInstrDesc.h"
31
#include "llvm/Pass.h"
32
#include "llvm/Support/CommandLine.h"
33
#include "llvm/Support/Debug.h"
34
#include "llvm/Support/ErrorHandling.h"
35
#include "llvm/Support/raw_ostream.h"
36
#include "llvm/Target/TargetSubtargetInfo.h"
37
#include <cassert>
38
#include <cstdint>
39
40
#define DEBUG_TYPE "opt-addr-mode"
41
42
using namespace llvm;
43
using namespace rdf;
44
45
static cl::opt<int> CodeGrowthLimit("hexagon-amode-growth-limit",
46
  cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode "
47
  "optimization"));
48
49
namespace llvm {
50
51
  FunctionPass *createHexagonOptAddrMode();
52
  void initializeHexagonOptAddrModePass(PassRegistry&);
53
54
} // end namespace llvm
55
56
namespace {
57
58
class HexagonOptAddrMode : public MachineFunctionPass {
59
public:
60
  static char ID;
61
62
405
  HexagonOptAddrMode() : MachineFunctionPass(ID) {}
63
64
401
  StringRef getPassName() const override {
65
401
    return "Optimize addressing mode of load/store";
66
401
  }
67
68
401
  void getAnalysisUsage(AnalysisUsage &AU) const override {
69
401
    MachineFunctionPass::getAnalysisUsage(AU);
70
401
    AU.addRequired<MachineDominatorTree>();
71
401
    AU.addRequired<MachineDominanceFrontier>();
72
401
    AU.setPreservesAll();
73
401
  }
74
75
  bool runOnMachineFunction(MachineFunction &MF) override;
76
77
private:
78
  using MISetType = DenseSet<MachineInstr *>;
79
  using InstrEvalMap = DenseMap<MachineInstr *, bool>;
80
81
  const HexagonInstrInfo *HII = nullptr;
82
  MachineDominatorTree *MDT = nullptr;
83
  DataFlowGraph *DFG = nullptr;
84
  DataFlowGraph::DefStackMap DefM;
85
  Liveness *LV = nullptr;
86
  MISetType Deleted;
87
88
  bool processBlock(NodeAddr<BlockNode *> BA);
89
  bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
90
                  NodeAddr<UseNode *> UseN, unsigned UseMOnum);
91
  bool analyzeUses(unsigned DefR, const NodeList &UNodeList,
92
                   InstrEvalMap &InstrEvalResult, short &SizeInc);
93
  bool hasRepForm(MachineInstr &MI, unsigned TfrDefR);
94
  bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr &MI,
95
                       const NodeList &UNodeList);
96
  void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);
97
  bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);
98
  short getBaseWithLongOffset(const MachineInstr &MI) const;
99
  bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
100
                   unsigned ImmOpNum);
101
  bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);
102
  bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
103
                    const MachineOperand &ImmOp, unsigned ImmOpNum);
104
};
105
106
} // end anonymous namespace
107
108
char HexagonOptAddrMode::ID = 0;
109
110
90.0k
INITIALIZE_PASS_BEGIN90.0k
(HexagonOptAddrMode, "amode-opt",
111
90.0k
                      "Optimize addressing mode", false, false)
112
90.0k
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
113
90.0k
INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
114
90.0k
INITIALIZE_PASS_END(HexagonOptAddrMode, "amode-opt", "Optimize addressing mode",
115
                    false, false)
116
117
997
bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) {
118
997
  const MCInstrDesc &MID = MI.getDesc();
119
997
120
997
  if (
(!MID.mayStore() && 997
!MID.mayLoad()628
) ||
HII->isPredicated(MI)997
)
121
0
    return false;
122
997
123
997
  
if (997
MID.mayStore()997
) {
124
369
    MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1);
125
369
    if (
StOp.isReg() && 369
StOp.getReg() == TfrDefR369
)
126
25
      return false;
127
972
  }
128
972
129
972
  
if (972
HII->getAddrMode(MI) == HexagonII::BaseRegOffset972
)
130
972
    // Tranform to Absolute plus register offset.
131
21
    return (HII->getBaseWithLongOffset(MI) >= 0);
132
951
  else 
if (951
HII->getAddrMode(MI) == HexagonII::BaseImmOffset951
)
133
951
    // Tranform to absolute addressing mode.
134
747
    return (HII->getAbsoluteForm(MI) >= 0);
135
204
136
204
  return false;
137
204
}
138
139
// Check if addasl instruction can be removed. This is possible only
140
// if it's feeding to only load/store instructions with base + register
141
// offset as these instruction can be tranformed to use 'absolute plus
142
// shifted register offset'.
143
// ex:
144
// Rs = ##foo
145
// Rx = addasl(Rs, Rt, #2)
146
// Rd = memw(Rx + #28)
147
// Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
148
149
bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN,
150
                                         MachineInstr &MI,
151
3
                                         const NodeList &UNodeList) {
152
3
  // check offset size in addasl. if 'offset > 3' return false
153
3
  const MachineOperand &OffsetOp = MI.getOperand(3);
154
3
  if (
!OffsetOp.isImm() || 3
OffsetOp.getImm() > 33
)
155
0
    return false;
156
3
157
3
  unsigned OffsetReg = MI.getOperand(2).getReg();
158
3
  RegisterRef OffsetRR;
159
3
  NodeId OffsetRegRD = 0;
160
6
  for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {
161
6
    RegisterRef RR = UA.Addr->getRegRef(*DFG);
162
6
    if (
OffsetReg == RR.Reg6
) {
163
3
      OffsetRR = RR;
164
3
      OffsetRegRD = UA.Addr->getReachingDef();
165
3
    }
166
6
  }
167
3
168
4
  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); 
I != E4
;
++I1
) {
169
3
    NodeAddr<UseNode *> UA = *I;
170
3
    NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
171
3
    if (UA.Addr->getFlags() & NodeAttrs::PhiRef)
172
0
      return false;
173
3
    NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(OffsetRR, IA);
174
3
    if (
(DFG->IsDef(AA) && 3
AA.Id != OffsetRegRD2
) ||
175
1
         AA.Addr->getReachingDef() != OffsetRegRD)
176
2
      return false;
177
1
178
1
    MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode();
179
1
    NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);
180
1
    // Reaching Def to an offset register can't be a phi.
181
1
    if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&
182
1
        MI.getParent() != UseMI.getParent())
183
0
    return false;
184
1
185
1
    const MCInstrDesc &UseMID = UseMI.getDesc();
186
1
    if (
(!UseMID.mayLoad() && 1
!UseMID.mayStore()1
) ||
187
1
        HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset ||
188
1
        getBaseWithLongOffset(UseMI) < 0)
189
0
      return false;
190
1
191
1
    // Addasl output can't be a store value.
192
1
    
if (1
UseMID.mayStore() && 1
UseMI.getOperand(2).isReg()1
&&
193
1
        UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg())
194
0
      return false;
195
1
196
1
    for (auto &Mo : UseMI.operands())
197
3
      
if (3
Mo.isFI()3
)
198
0
        return false;
199
3
  }
200
1
  return true;
201
3
}
202
203
bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,
204
121
                                            NodeList &UNodeList) {
205
1.16k
  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); 
I != E1.16k
;
++I1.03k
) {
206
1.04k
    NodeAddr<UseNode *> UN = *I;
207
1.04k
    RegisterRef UR = UN.Addr->getRegRef(*DFG);
208
1.04k
    NodeSet Visited, Defs;
209
1.04k
    const auto &P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
210
1.04k
    if (
!P.second1.04k
) {
211
0
      DEBUG({
212
0
        dbgs() << "*** Unable to collect all reaching defs for use ***\n"
213
0
               << PrintNode<UseNode*>(UN, *DFG) << '\n'
214
0
               << "The program's complexity may exceed the limits.\n";
215
0
      });
216
0
      return false;
217
0
    }
218
1.04k
    const auto &ReachingDefs = P.first;
219
1.04k
    if (
ReachingDefs.size() > 11.04k
) {
220
9
      DEBUG({
221
9
        dbgs() << "*** Multiple Reaching Defs found!!! ***\n";
222
9
        for (auto DI : ReachingDefs) {
223
9
          NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);
224
9
          NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);
225
9
          dbgs() << "\t\t[Reaching Def]: "
226
9
                 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
227
9
        }
228
9
      });
229
9
      return false;
230
9
    }
231
1.04k
  }
232
112
  return true;
233
121
}
234
235
void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
236
122
                                        NodeList &UNodeList) {
237
122
  for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {
238
122
    DEBUG(dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG)
239
122
                 << "\n");
240
122
    RegisterRef DR = DFG->getPRI().normalize(DA.Addr->getRegRef(*DFG));
241
122
242
122
    auto UseSet = LV->getAllReachedUses(DR, DA);
243
122
244
1.06k
    for (auto UI : UseSet) {
245
1.06k
      NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);
246
1.06k
      DEBUG({
247
1.06k
        NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);
248
1.06k
        dbgs() << "\t\t\t[Reached Use]: "
249
1.06k
               << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
250
1.06k
      });
251
1.06k
252
1.06k
      if (
UA.Addr->getFlags() & NodeAttrs::PhiRef1.06k
) {
253
15
        NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);
254
15
        NodeId id = PA.Id;
255
15
        const Liveness::RefMap &phiUse = LV->getRealUses(id);
256
15
        DEBUG(dbgs() << "\t\t\t\tphi real Uses"
257
15
                     << Print<Liveness::RefMap>(phiUse, *DFG) << "\n");
258
15
        if (
!phiUse.empty()15
) {
259
14
          for (auto I : phiUse) {
260
14
            if (!DFG->getPRI().alias(RegisterRef(I.first), DR))
261
3
              continue;
262
11
            auto phiUseSet = I.second;
263
23
            for (auto phiUI : phiUseSet) {
264
23
              NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first);
265
23
              UNodeList.push_back(phiUA);
266
23
            }
267
14
          }
268
10
        }
269
15
      } else
270
1.04k
        UNodeList.push_back(UA);
271
1.06k
    }
272
122
  }
273
122
}
274
275
bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,
276
                                     const NodeList &UNodeList,
277
                                     InstrEvalMap &InstrEvalResult,
278
109
                                     short &SizeInc) {
279
109
  bool KeepTfr = false;
280
109
  bool HasRepInstr = false;
281
109
  InstrEvalResult.clear();
282
109
283
1.14k
  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); 
I != E1.14k
;
++I1.03k
) {
284
1.03k
    bool CanBeReplaced = false;
285
1.03k
    NodeAddr<UseNode *> UN = *I;
286
1.03k
    NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
287
1.03k
    MachineInstr &MI = *SN.Addr->getCode();
288
1.03k
    const MCInstrDesc &MID = MI.getDesc();
289
1.03k
    if (
(MID.mayLoad() || 1.03k
MID.mayStore()384
)) {
290
997
      if (
!hasRepForm(MI, tfrDefR)997
) {
291
967
        KeepTfr = true;
292
967
        continue;
293
967
      }
294
30
      SizeInc++;
295
30
      CanBeReplaced = true;
296
1.03k
    } else 
if (39
MI.getOpcode() == Hexagon::S2_addasl_rrri39
) {
297
3
      NodeList AddaslUseList;
298
3
299
3
      DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n");
300
3
      getAllRealUses(SN, AddaslUseList);
301
3
      // Process phi nodes.
302
3
      if (allValidCandidates(SN, AddaslUseList) &&
303
3
          
canRemoveAddasl(SN, MI, AddaslUseList)3
) {
304
1
        SizeInc += AddaslUseList.size();
305
1
        SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed.
306
1
        CanBeReplaced = true;
307
1
      } else
308
2
        SizeInc++;
309
3
    } else
310
39
      // Currently, only load/store and addasl are handled.
311
39
      // Some other instructions to consider -
312
39
      // A2_add -> A2_addi
313
39
      // M4_mpyrr_addr -> M4_mpyrr_addi
314
36
      KeepTfr = true;
315
1.03k
316
69
    InstrEvalResult[&MI] = CanBeReplaced;
317
69
    HasRepInstr |= CanBeReplaced;
318
69
  }
319
109
320
109
  // Reduce total size by 2 if original tfr can be deleted.
321
109
  if (!KeepTfr)
322
17
    SizeInc -= 2;
323
109
324
109
  return HasRepInstr;
325
109
}
326
327
bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
328
13
                                    unsigned ImmOpNum) {
329
13
  bool Changed = false;
330
13
  MachineBasicBlock *BB = OldMI->getParent();
331
13
  auto UsePos = MachineBasicBlock::iterator(OldMI);
332
13
  MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
333
13
  ++InsertPt;
334
13
  unsigned OpStart;
335
13
  unsigned OpEnd = OldMI->getNumOperands();
336
13
  MachineInstrBuilder MIB;
337
13
338
13
  if (
ImmOpNum == 113
) {
339
13
    if (
HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset13
) {
340
6
      short NewOpCode = HII->getBaseWithLongOffset(*OldMI);
341
6
      assert(NewOpCode >= 0 && "Invalid New opcode\n");
342
6
      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
343
6
      MIB.add(OldMI->getOperand(0));
344
6
      MIB.add(OldMI->getOperand(2));
345
6
      MIB.add(OldMI->getOperand(3));
346
6
      MIB.add(ImmOp);
347
6
      OpStart = 4;
348
6
      Changed = true;
349
13
    } else 
if (7
HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset7
) {
350
7
      short NewOpCode = HII->getAbsoluteForm(*OldMI);
351
7
      assert(NewOpCode >= 0 && "Invalid New opcode\n");
352
7
      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))
353
7
                .add(OldMI->getOperand(0));
354
7
      const GlobalValue *GV = ImmOp.getGlobal();
355
7
      int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm();
356
7
357
7
      MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
358
7
      OpStart = 3;
359
7
      Changed = true;
360
7
    } else
361
0
      Changed = false;
362
13
363
13
    DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
364
13
    DEBUG(dbgs() << "[TO]: " << MIB << "\n");
365
0
  } else 
if (0
ImmOpNum == 2 && 0
OldMI->getOperand(3).getImm() == 00
) {
366
0
    short NewOpCode = HII->xformRegToImmOffset(*OldMI);
367
0
    assert(NewOpCode >= 0 && "Invalid New opcode\n");
368
0
    MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
369
0
    MIB.add(OldMI->getOperand(0));
370
0
    MIB.add(OldMI->getOperand(1));
371
0
    MIB.add(ImmOp);
372
0
    OpStart = 4;
373
0
    Changed = true;
374
0
    DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
375
0
    DEBUG(dbgs() << "[TO]: " << MIB << "\n");
376
0
  }
377
13
378
13
  if (Changed)
379
13
    
for (unsigned i = OpStart; 13
i < OpEnd13
;
++i0
)
380
0
      MIB.add(OldMI->getOperand(i));
381
13
382
13
  return Changed;
383
13
}
384
385
bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
386
3
                                     unsigned ImmOpNum) {
387
3
  bool Changed = false;
388
3
  unsigned OpStart;
389
3
  unsigned OpEnd = OldMI->getNumOperands();
390
3
  MachineBasicBlock *BB = OldMI->getParent();
391
3
  auto UsePos = MachineBasicBlock::iterator(OldMI);
392
3
  MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
393
3
  ++InsertPt;
394
3
  MachineInstrBuilder MIB;
395
3
  if (
ImmOpNum == 03
) {
396
3
    if (
HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset3
) {
397
3
      short NewOpCode = HII->getBaseWithLongOffset(*OldMI);
398
3
      assert(NewOpCode >= 0 && "Invalid New opcode\n");
399
3
      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
400
3
      MIB.add(OldMI->getOperand(1));
401
3
      MIB.add(OldMI->getOperand(2));
402
3
      MIB.add(ImmOp);
403
3
      MIB.add(OldMI->getOperand(3));
404
3
      OpStart = 4;
405
3
    } else 
if (0
HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset0
) {
406
0
      short NewOpCode = HII->getAbsoluteForm(*OldMI);
407
0
      assert(NewOpCode >= 0 && "Invalid New opcode\n");
408
0
      MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
409
0
      const GlobalValue *GV = ImmOp.getGlobal();
410
0
      int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm();
411
0
      MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
412
0
      MIB.add(OldMI->getOperand(2));
413
0
      OpStart = 3;
414
0
    }
415
3
    Changed = true;
416
3
    DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
417
3
    DEBUG(dbgs() << "[TO]: " << MIB << "\n");
418
0
  } else 
if (0
ImmOpNum == 1 && 0
OldMI->getOperand(2).getImm() == 00
) {
419
0
    short NewOpCode = HII->xformRegToImmOffset(*OldMI);
420
0
    assert(NewOpCode >= 0 && "Invalid New opcode\n");
421
0
    MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
422
0
    MIB.add(OldMI->getOperand(0));
423
0
    MIB.add(ImmOp);
424
0
    MIB.add(OldMI->getOperand(1));
425
0
    OpStart = 2;
426
0
    Changed = true;
427
0
    DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
428
0
    DEBUG(dbgs() << "[TO]: " << MIB << "\n");
429
0
  }
430
3
  if (Changed)
431
3
    
for (unsigned i = OpStart; 3
i < OpEnd3
;
++i0
)
432
0
      MIB.add(OldMI->getOperand(i));
433
3
434
3
  return Changed;
435
3
}
436
437
2
short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const {
438
2
  if (
HII->getAddrMode(MI) == HexagonII::BaseImmOffset2
) {
439
2
    short TempOpCode = HII->getBaseWithRegOffset(MI);
440
2
    return HII->getBaseWithLongOffset(TempOpCode);
441
2
  } else
442
0
    return HII->getBaseWithLongOffset(MI);
443
0
}
444
445
bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
446
                                      MachineInstr *AddAslMI,
447
                                      const MachineOperand &ImmOp,
448
1
                                      unsigned ImmOpNum) {
449
1
  NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);
450
1
451
1
  DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");
452
1
453
1
  NodeList UNodeList;
454
1
  getAllRealUses(SA, UNodeList);
455
1
456
2
  for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); 
I != E2
;
++I1
) {
457
1
    NodeAddr<UseNode *> UseUN = *I;
458
1
    assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&
459
1
           "Can't transform this 'AddAsl' instruction!");
460
1
461
1
    NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);
462
1
    DEBUG(dbgs() << "[InstrNode]: " << Print<NodeAddr<InstrNode *>>(UseIA, *DFG)
463
1
                 << "\n");
464
1
    MachineInstr *UseMI = UseIA.Addr->getCode();
465
1
    DEBUG(dbgs() << "[MI <BB#" << UseMI->getParent()->getNumber()
466
1
                 << ">]: " << *UseMI << "\n");
467
1
    const MCInstrDesc &UseMID = UseMI->getDesc();
468
1
    assert(HII->getAddrMode(*UseMI) == HexagonII::BaseImmOffset);
469
1
470
1
    auto UsePos = MachineBasicBlock::iterator(UseMI);
471
1
    MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
472
1
    short NewOpCode = getBaseWithLongOffset(*UseMI);
473
1
    assert(NewOpCode >= 0 && "Invalid New opcode\n");
474
1
475
1
    unsigned OpStart;
476
1
    unsigned OpEnd = UseMI->getNumOperands();
477
1
478
1
    MachineBasicBlock *BB = UseMI->getParent();
479
1
    MachineInstrBuilder MIB =
480
1
        BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode));
481
1
    // change mem(Rs + # ) -> mem(Rt << # + ##)
482
1
    if (
UseMID.mayLoad()1
) {
483
0
      MIB.add(UseMI->getOperand(0));
484
0
      MIB.add(AddAslMI->getOperand(2));
485
0
      MIB.add(AddAslMI->getOperand(3));
486
0
      const GlobalValue *GV = ImmOp.getGlobal();
487
0
      MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm()+ImmOp.getOffset(),
488
0
                           ImmOp.getTargetFlags());
489
0
      OpStart = 3;
490
1
    } else 
if (1
UseMID.mayStore()1
) {
491
1
      MIB.add(AddAslMI->getOperand(2));
492
1
      MIB.add(AddAslMI->getOperand(3));
493
1
      const GlobalValue *GV = ImmOp.getGlobal();
494
1
      MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm()+ImmOp.getOffset(),
495
1
                           ImmOp.getTargetFlags());
496
1
      MIB.add(UseMI->getOperand(2));
497
1
      OpStart = 3;
498
1
    } else
499
0
      llvm_unreachable("Unhandled instruction");
500
1
501
1
    
for (unsigned i = OpStart; 1
i < OpEnd1
;
++i0
)
502
0
      MIB.add(UseMI->getOperand(i));
503
1
504
1
    Deleted.insert(UseMI);
505
1
  }
506
1
507
1
  return true;
508
1
}
509
510
bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
511
                                    NodeAddr<UseNode *> UseN,
512
17
                                    unsigned UseMOnum) {
513
17
  const MachineOperand ImmOp = TfrMI->getOperand(1);
514
17
  const MCInstrDesc &MID = UseMI->getDesc();
515
17
  unsigned Changed = false;
516
17
  if (MID.mayLoad())
517
13
    Changed = changeLoad(UseMI, ImmOp, UseMOnum);
518
4
  else 
if (4
MID.mayStore()4
)
519
3
    Changed = changeStore(UseMI, ImmOp, UseMOnum);
520
1
  else 
if (1
UseMI->getOpcode() == Hexagon::S2_addasl_rrri1
)
521
1
    Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
522
17
523
17
  if (Changed)
524
17
    Deleted.insert(UseMI);
525
17
526
17
  return Changed;
527
17
}
528
529
2.04k
bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
530
2.04k
  bool Changed = false;
531
2.04k
532
15.6k
  for (auto IA : BA.Addr->members(*DFG)) {
533
15.6k
    if (!DFG->IsCode<NodeAttrs::Stmt>(IA))
534
4.11k
      continue;
535
11.5k
536
11.5k
    NodeAddr<StmtNode *> SA = IA;
537
11.5k
    MachineInstr *MI = SA.Addr->getCode();
538
11.5k
    if (MI->getOpcode() != Hexagon::A2_tfrsi ||
539
669
        !MI->getOperand(1).isGlobal())
540
11.4k
      continue;
541
118
542
118
    
DEBUG118
(dbgs() << "[Analyzing " << HII->getName(MI->getOpcode()) << "]: "
543
118
                 << *MI << "\n\t[InstrNode]: "
544
118
                 << Print<NodeAddr<InstrNode *>>(IA, *DFG) << '\n');
545
118
546
118
    NodeList UNodeList;
547
118
    getAllRealUses(SA, UNodeList);
548
118
549
118
    if (!allValidCandidates(SA, UNodeList))
550
9
      continue;
551
109
552
109
    short SizeInc = 0;
553
109
    unsigned DefR = MI->getOperand(0).getReg();
554
109
    InstrEvalMap InstrEvalResult;
555
109
556
109
    // Analyze all uses and calculate increase in size. Perform the optimization
557
109
    // only if there is no increase in size.
558
109
    if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
559
92
      continue;
560
17
    
if (17
SizeInc > CodeGrowthLimit17
)
561
4
      continue;
562
13
563
13
    bool KeepTfr = false;
564
13
565
13
    DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size() << "\n");
566
13
    DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
567
30
    for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); 
I != E30
;
++I17
) {
568
17
      NodeAddr<UseNode *> UseN = *I;
569
17
      assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&
570
17
             "Found a PhiRef node as a real reached use!!");
571
17
572
17
      NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
573
17
      MachineInstr *UseMI = OwnerN.Addr->getCode();
574
17
      DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()
575
17
                   << ">]: " << *UseMI << "\n");
576
17
577
17
      int UseMOnum = -1;
578
17
      unsigned NumOperands = UseMI->getNumOperands();
579
61
      for (unsigned j = 0; 
j < NumOperands - 161
;
++j44
) {
580
44
        const MachineOperand &op = UseMI->getOperand(j);
581
44
        if (
op.isReg() && 44
op.isUse()41
&&
DefR == op.getReg()27
)
582
17
          UseMOnum = j;
583
44
      }
584
17
      assert(UseMOnum >= 0 && "Invalid reached use!");
585
17
586
17
      if (InstrEvalResult[UseMI])
587
17
        // Change UseMI if replacement is possible.
588
17
        Changed |= xformUseMI(MI, UseMI, UseN, UseMOnum);
589
17
      else
590
0
        KeepTfr = true;
591
17
    }
592
13
    if (!KeepTfr)
593
13
      Deleted.insert(MI);
594
15.6k
  }
595
2.04k
  return Changed;
596
2.04k
}
597
598
857
bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
599
857
  if (skipFunction(*MF.getFunction()))
600
0
    return false;
601
857
602
857
  bool Changed = false;
603
857
  auto &HST = MF.getSubtarget<HexagonSubtarget>();
604
857
  auto &MRI = MF.getRegInfo();
605
857
  HII = HST.getInstrInfo();
606
857
  const auto &MDF = getAnalysis<MachineDominanceFrontier>();
607
857
  MDT = &getAnalysis<MachineDominatorTree>();
608
857
  const auto &TRI = *MF.getSubtarget().getRegisterInfo();
609
857
  const TargetOperandInfo TOI(*HII);
610
857
611
857
  DataFlowGraph G(MF, *HII, TRI, *MDT, MDF, TOI);
612
857
  // Need to keep dead phis because we can propagate uses of registers into
613
857
  // nodes dominated by those would-be phis.
614
857
  G.build(BuildOptions::KeepDeadPhis);
615
857
  DFG = &G;
616
857
617
857
  Liveness L(MRI, *DFG);
618
857
  L.computePhiInfo();
619
857
  LV = &L;
620
857
621
857
  Deleted.clear();
622
857
  NodeAddr<FuncNode *> FA = DFG->getFunc();
623
857
  DEBUG(dbgs() << "==== [RefMap#]=====:\n "
624
857
               << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");
625
857
626
857
  for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))
627
2.04k
    Changed |= processBlock(BA);
628
857
629
857
  for (auto MI : Deleted)
630
31
    MI->eraseFromParent();
631
857
632
857
  if (
Changed857
) {
633
13
    G.build();
634
13
    L.computeLiveIns();
635
13
    L.resetLiveIns();
636
13
    L.resetKills();
637
13
  }
638
857
639
857
  return Changed;
640
857
}
641
642
//===----------------------------------------------------------------------===//
643
//                         Public Constructor Functions
644
//===----------------------------------------------------------------------===//
645
646
403
FunctionPass *llvm::createHexagonOptAddrMode() {
647
403
  return new HexagonOptAddrMode();
648
403
}