Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/Hexagon/HexagonFixupHwLoops.cpp
Line
Count
Source (jump to first uncovered line)
1
//===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
// The loop start address in the LOOPn instruction is encoded as a distance
8
// from the LOOPn instruction itself. If the start address is too far from
9
// the LOOPn instruction, the instruction needs to use a constant extender.
10
// This pass will identify and convert such LOOPn instructions to a proper
11
// form.
12
//===----------------------------------------------------------------------===//
13
14
#include "Hexagon.h"
15
#include "HexagonTargetMachine.h"
16
#include "llvm/ADT/DenseMap.h"
17
#include "llvm/CodeGen/MachineFunction.h"
18
#include "llvm/CodeGen/MachineFunctionPass.h"
19
#include "llvm/CodeGen/MachineInstrBuilder.h"
20
#include "llvm/CodeGen/Passes.h"
21
#include "llvm/CodeGen/TargetInstrInfo.h"
22
#include "llvm/Support/MathExtras.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
862
    HexagonFixupHwLoops() : MachineFunctionPass(ID) {
42
862
      initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
43
862
    }
44
45
    bool runOnMachineFunction(MachineFunction &MF) override;
46
47
858
    MachineFunctionProperties getRequiredProperties() const override {
48
858
      return MachineFunctionProperties().set(
49
858
          MachineFunctionProperties::Property::NoVRegs);
50
858
    }
51
52
4.22k
    StringRef getPassName() const override {
53
4.22k
      return "Hexagon Hardware Loop Fixup";
54
4.22k
    }
55
56
858
    void getAnalysisUsage(AnalysisUsage &AU) const override {
57
858
      AU.setPreservesCFG();
58
858
      MachineFunctionPass::getAnalysisUsage(AU);
59
858
    }
60
61
  private:
62
    /// 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
    /// 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
862
FunctionPass *llvm::createHexagonFixupHwLoops() {
80
862
  return new HexagonFixupHwLoops();
81
862
}
82
83
/// Returns true if the instruction is a hardware loop instruction.
84
28.0k
static bool isHardwareLoop(const MachineInstr &MI) {
85
28.0k
  return MI.getOpcode() == Hexagon::J2_loop0r ||
86
28.0k
         
MI.getOpcode() == Hexagon::J2_loop0i27.8k
||
87
28.0k
         
MI.getOpcode() == Hexagon::J2_loop1r27.8k
||
88
28.0k
         
MI.getOpcode() == Hexagon::J2_loop1i27.8k
;
89
28.0k
}
90
91
3.36k
bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
92
3.36k
  if (skipFunction(MF.getFunction()))
93
10
    return false;
94
3.35k
  return fixupLoopInstrs(MF);
95
3.35k
}
96
97
/// 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
3.35k
bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
106
3.35k
107
3.35k
  // Offset of the current instruction from the start.
108
3.35k
  unsigned InstOffset = 0;
109
3.35k
  // Map for each basic block to it's first instruction.
110
3.35k
  DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset;
111
3.35k
112
3.35k
  const HexagonInstrInfo *HII =
113
3.35k
      static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
114
3.35k
115
3.35k
  // First pass - compute the offset of each basic block.
116
4.99k
  for (const MachineBasicBlock &MBB : MF) {
117
4.99k
    if (MBB.getAlignment()) {
118
404
      // Although we don't know the exact layout of the final code, we need
119
404
      // to account for alignment padding somehow. This heuristic pads each
120
404
      // aligned basic block according to the alignment value.
121
404
      int ByteAlign = (1u << MBB.getAlignment()) - 1;
122
404
      InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign);
123
404
    }
124
4.99k
125
4.99k
    BlockToInstOffset[&MBB] = InstOffset;
126
4.99k
    for (const MachineInstr &MI : MBB)
127
28.1k
      InstOffset += HII->getSize(MI);
128
4.99k
  }
129
3.35k
130
3.35k
  // Second pass - check each loop instruction to see if it needs to be
131
3.35k
  // converted.
132
3.35k
  bool Changed = false;
133
4.99k
  for (MachineBasicBlock &MBB : MF) {
134
4.99k
    InstOffset = BlockToInstOffset[&MBB];
135
4.99k
136
4.99k
    // Loop over all the instructions.
137
4.99k
    MachineBasicBlock::iterator MII = MBB.begin();
138
4.99k
    MachineBasicBlock::iterator MIE = MBB.end();
139
33.1k
    while (MII != MIE) {
140
28.1k
      unsigned InstSize = HII->getSize(*MII);
141
28.1k
      if (MII->isMetaInstruction()) {
142
89
        ++MII;
143
89
        continue;
144
89
      }
145
28.0k
      if (isHardwareLoop(*MII)) {
146
229
        assert(MII->getOperand(0).isMBB() &&
147
229
               "Expect a basic block as loop operand");
148
229
        MachineBasicBlock *TargetBB = MII->getOperand(0).getMBB();
149
229
        unsigned Diff = AbsoluteDifference(InstOffset,
150
229
                                           BlockToInstOffset[TargetBB]);
151
229
        if (Diff > MaxLoopRange) {
152
1
          useExtLoopInstr(MF, MII);
153
1
          MII = MBB.erase(MII);
154
1
          Changed = true;
155
228
        } else {
156
228
          ++MII;
157
228
        }
158
27.8k
      } else {
159
27.8k
        ++MII;
160
27.8k
      }
161
28.0k
      InstOffset += InstSize;
162
28.0k
    }
163
4.99k
  }
164
3.35k
165
3.35k
  return Changed;
166
3.35k
}
167
168
/// Replace loop instructions with the constant extended version.
169
void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
170
1
                                          MachineBasicBlock::iterator &MII) {
171
1
  const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
172
1
  MachineBasicBlock *MBB = MII->getParent();
173
1
  DebugLoc DL = MII->getDebugLoc();
174
1
  MachineInstrBuilder MIB;
175
1
  unsigned newOp;
176
1
  switch (MII->getOpcode()) {
177
1
  case Hexagon::J2_loop0r:
178
1
    newOp = Hexagon::J2_loop0rext;
179
1
    break;
180
1
  case Hexagon::J2_loop0i:
181
0
    newOp = Hexagon::J2_loop0iext;
182
0
    break;
183
1
  case Hexagon::J2_loop1r:
184
0
    newOp = Hexagon::J2_loop1rext;
185
0
    break;
186
1
  case Hexagon::J2_loop1i:
187
0
    newOp = Hexagon::J2_loop1iext;
188
0
    break;
189
1
  default:
190
0
    llvm_unreachable("Invalid Hardware Loop Instruction.");
191
1
  }
192
1
  MIB = BuildMI(*MBB, MII, DL, TII->get(newOp));
193
1
194
6
  for (unsigned i = 0; i < MII->getNumOperands(); 
++i5
)
195
5
    MIB.add(MII->getOperand(i));
196
1
}