Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AArch64/AArch64CompressJumpTables.cpp
Line
Count
Source (jump to first uncovered line)
1
//==-- AArch64CompressJumpTables.cpp - Compress jump tables for AArch64 --====//
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
// This pass looks at the basic blocks each jump-table refers to and works out
8
// whether they can be emitted in a compressed form (with 8 or 16-bit
9
// entries). If so, it changes the opcode and flags them in the associated
10
// AArch64FunctionInfo.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "AArch64.h"
15
#include "AArch64MachineFunctionInfo.h"
16
#include "AArch64Subtarget.h"
17
#include "llvm/ADT/Statistic.h"
18
#include "llvm/CodeGen/MachineFunctionPass.h"
19
#include "llvm/CodeGen/MachineJumpTableInfo.h"
20
#include "llvm/CodeGen/TargetInstrInfo.h"
21
#include "llvm/CodeGen/TargetSubtargetInfo.h"
22
#include "llvm/MC/MCContext.h"
23
#include "llvm/Support/Debug.h"
24
25
using namespace llvm;
26
27
#define DEBUG_TYPE "aarch64-jump-tables"
28
29
STATISTIC(NumJT8, "Number of jump-tables with 1-byte entries");
30
STATISTIC(NumJT16, "Number of jump-tables with 2-byte entries");
31
STATISTIC(NumJT32, "Number of jump-tables with 4-byte entries");
32
33
namespace {
34
class AArch64CompressJumpTables : public MachineFunctionPass {
35
  const TargetInstrInfo *TII;
36
  MachineFunction *MF;
37
  SmallVector<int, 8> BlockInfo;
38
39
  int computeBlockSize(MachineBasicBlock &MBB);
40
  void scanFunction();
41
42
  bool compressJumpTable(MachineInstr &MI, int Offset);
43
44
public:
45
  static char ID;
46
8.62k
  AArch64CompressJumpTables() : MachineFunctionPass(ID) {
47
8.62k
    initializeAArch64CompressJumpTablesPass(*PassRegistry::getPassRegistry());
48
8.62k
  }
49
50
  bool runOnMachineFunction(MachineFunction &MF) override;
51
52
8.58k
  MachineFunctionProperties getRequiredProperties() const override {
53
8.58k
    return MachineFunctionProperties().set(
54
8.58k
        MachineFunctionProperties::Property::NoVRegs);
55
8.58k
  }
56
265k
  StringRef getPassName() const override {
57
265k
    return "AArch64 Compress Jump Tables";
58
265k
  }
59
};
60
char AArch64CompressJumpTables::ID = 0;
61
}
62
63
INITIALIZE_PASS(AArch64CompressJumpTables, DEBUG_TYPE,
64
                "AArch64 compress jump tables pass", false, false)
65
66
2.06M
int AArch64CompressJumpTables::computeBlockSize(MachineBasicBlock &MBB) {
67
2.06M
  int Size = 0;
68
2.06M
  for (const MachineInstr &MI : MBB)
69
14.9M
    Size += TII->getInstSizeInBytes(MI);
70
2.06M
  return Size;
71
2.06M
}
72
73
256k
void AArch64CompressJumpTables::scanFunction() {
74
256k
  BlockInfo.clear();
75
256k
  BlockInfo.resize(MF->getNumBlockIDs());
76
256k
77
256k
  int Offset = 0;
78
2.06M
  for (MachineBasicBlock &MBB : *MF) {
79
2.06M
    BlockInfo[MBB.getNumber()] = Offset;
80
2.06M
    Offset += computeBlockSize(MBB);
81
2.06M
  }
82
256k
}
83
84
bool AArch64CompressJumpTables::compressJumpTable(MachineInstr &MI,
85
14.9M
                                                  int Offset) {
86
14.9M
  if (MI.getOpcode() != AArch64::JumpTableDest32)
87
14.9M
    return false;
88
2.40k
89
2.40k
  int JTIdx = MI.getOperand(4).getIndex();
90
2.40k
  auto &JTInfo = *MF->getJumpTableInfo();
91
2.40k
  const MachineJumpTableEntry &JT = JTInfo.getJumpTables()[JTIdx];
92
2.40k
93
2.40k
  // The jump-table might have been optimized away.
94
2.40k
  if (JT.MBBs.empty())
95
0
    return false;
96
2.40k
97
2.40k
  int MaxOffset = std::numeric_limits<int>::min(),
98
2.40k
      MinOffset = std::numeric_limits<int>::max();
99
2.40k
  MachineBasicBlock *MinBlock = nullptr;
100
36.1k
  for (auto Block : JT.MBBs) {
101
36.1k
    int BlockOffset = BlockInfo[Block->getNumber()];
102
36.1k
    assert(BlockOffset % 4 == 0 && "misaligned basic block");
103
36.1k
104
36.1k
    MaxOffset = std::max(MaxOffset, BlockOffset);
105
36.1k
    if (BlockOffset <= MinOffset) {
106
9.16k
      MinOffset = BlockOffset;
107
9.16k
      MinBlock = Block;
108
9.16k
    }
109
36.1k
  }
110
2.40k
  assert(MinBlock && "Failed to find minimum offset block");
111
2.40k
112
2.40k
  // The ADR instruction needed to calculate the address of the first reachable
113
2.40k
  // basic block can address +/-1MB.
114
2.40k
  if (!isInt<21>(MinOffset - Offset)) {
115
2
    ++NumJT32;
116
2
    return false;
117
2
  }
118
2.40k
119
2.40k
  int Span = MaxOffset - MinOffset;
120
2.40k
  auto AFI = MF->getInfo<AArch64FunctionInfo>();
121
2.40k
  if (isUInt<8>(Span / 4)) {
122
2.16k
    AFI->setJumpTableEntryInfo(JTIdx, 1, MinBlock->getSymbol());
123
2.16k
    MI.setDesc(TII->get(AArch64::JumpTableDest8));
124
2.16k
    ++NumJT8;
125
2.16k
    return true;
126
2.16k
  } else 
if (235
isUInt<16>(Span / 4)235
) {
127
235
    AFI->setJumpTableEntryInfo(JTIdx, 2, MinBlock->getSymbol());
128
235
    MI.setDesc(TII->get(AArch64::JumpTableDest16));
129
235
    ++NumJT16;
130
235
    return true;
131
235
  }
132
0
133
0
  ++NumJT32;
134
0
  return false;
135
0
}
136
137
257k
bool AArch64CompressJumpTables::runOnMachineFunction(MachineFunction &MFIn) {
138
257k
  bool Changed = false;
139
257k
  MF = &MFIn;
140
257k
141
257k
  const auto &ST = MF->getSubtarget<AArch64Subtarget>();
142
257k
  TII = ST.getInstrInfo();
143
257k
144
257k
  if (ST.force32BitJumpTables() && 
!MF->getFunction().hasMinSize()813
)
145
809
    return false;
146
256k
147
256k
  scanFunction();
148
256k
149
2.06M
  for (MachineBasicBlock &MBB : *MF) {
150
2.06M
    int Offset = BlockInfo[MBB.getNumber()];
151
14.9M
    for (MachineInstr &MI : MBB) {
152
14.9M
      Changed |= compressJumpTable(MI, Offset);
153
14.9M
      Offset += TII->getInstSizeInBytes(MI);
154
14.9M
    }
155
2.06M
  }
156
256k
157
256k
  return Changed;
158
256k
}
159
160
8.62k
FunctionPass *llvm::createAArch64CompressJumpTablesPass() {
161
8.62k
  return new AArch64CompressJumpTables();
162
8.62k
}