Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- WebAssemblyPeephole.cpp - WebAssembly Peephole Optimiztions -------===//
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
//===----------------------------------------------------------------------===//
8
///
9
/// \file
10
/// Late peephole optimizations for WebAssembly.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
15
#include "WebAssembly.h"
16
#include "WebAssemblyMachineFunctionInfo.h"
17
#include "WebAssemblySubtarget.h"
18
#include "llvm/Analysis/TargetLibraryInfo.h"
19
#include "llvm/CodeGen/MachineFunctionPass.h"
20
#include "llvm/CodeGen/MachineInstrBuilder.h"
21
#include "llvm/CodeGen/MachineRegisterInfo.h"
22
using namespace llvm;
23
24
#define DEBUG_TYPE "wasm-peephole"
25
26
static cl::opt<bool> DisableWebAssemblyFallthroughReturnOpt(
27
    "disable-wasm-fallthrough-return-opt", cl::Hidden,
28
    cl::desc("WebAssembly: Disable fallthrough-return optimizations."),
29
    cl::init(false));
30
31
namespace {
32
class WebAssemblyPeephole final : public MachineFunctionPass {
33
4.72k
  StringRef getPassName() const override {
34
4.72k
    return "WebAssembly late peephole optimizer";
35
4.72k
  }
36
37
412
  void getAnalysisUsage(AnalysisUsage &AU) const override {
38
412
    AU.setPreservesCFG();
39
412
    AU.addRequired<TargetLibraryInfoWrapperPass>();
40
412
    MachineFunctionPass::getAnalysisUsage(AU);
41
412
  }
42
43
  bool runOnMachineFunction(MachineFunction &MF) override;
44
45
public:
46
  static char ID;
47
413
  WebAssemblyPeephole() : MachineFunctionPass(ID) {}
48
};
49
} // end anonymous namespace
50
51
char WebAssemblyPeephole::ID = 0;
52
INITIALIZE_PASS(WebAssemblyPeephole, DEBUG_TYPE,
53
                "WebAssembly peephole optimizations", false, false)
54
55
413
FunctionPass *llvm::createWebAssemblyPeephole() {
56
413
  return new WebAssemblyPeephole();
57
413
}
58
59
/// If desirable, rewrite NewReg to a drop register.
60
static bool maybeRewriteToDrop(unsigned OldReg, unsigned NewReg,
61
                               MachineOperand &MO, WebAssemblyFunctionInfo &MFI,
62
24
                               MachineRegisterInfo &MRI) {
63
24
  bool Changed = false;
64
24
  if (OldReg == NewReg) {
65
1
    Changed = true;
66
1
    unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg));
67
1
    MO.setReg(NewReg);
68
1
    MO.setIsDead();
69
1
    MFI.stackifyVReg(NewReg);
70
1
  }
71
24
  return Changed;
72
24
}
73
74
static bool maybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB,
75
                                      const MachineFunction &MF,
76
                                      WebAssemblyFunctionInfo &MFI,
77
                                      MachineRegisterInfo &MRI,
78
                                      const WebAssemblyInstrInfo &TII,
79
                                      unsigned FallthroughOpc,
80
4.31k
                                      unsigned CopyLocalOpc) {
81
4.31k
  if (DisableWebAssemblyFallthroughReturnOpt)
82
3.59k
    return false;
83
717
  if (&MBB != &MF.back())
84
6
    return false;
85
711
86
711
  MachineBasicBlock::iterator End = MBB.end();
87
711
  --End;
88
711
  assert(End->getOpcode() == WebAssembly::END_FUNCTION);
89
711
  --End;
90
711
  if (&MI != &*End)
91
0
    return false;
92
711
93
711
  if (FallthroughOpc != WebAssembly::FALLTHROUGH_RETURN_VOID) {
94
456
    // If the operand isn't stackified, insert a COPY to read the operand and
95
456
    // stackify it.
96
456
    MachineOperand &MO = MI.getOperand(0);
97
456
    unsigned Reg = MO.getReg();
98
456
    if (!MFI.isVRegStackified(Reg)) {
99
4
      unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg));
100
4
      BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(CopyLocalOpc), NewReg)
101
4
          .addReg(Reg);
102
4
      MO.setReg(NewReg);
103
4
      MFI.stackifyVReg(NewReg);
104
4
    }
105
456
  }
106
711
107
711
  // Rewrite the return.
108
711
  MI.setDesc(TII.get(FallthroughOpc));
109
711
  return true;
110
711
}
111
112
4.31k
bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
113
4.31k
  LLVM_DEBUG({
114
4.31k
    dbgs() << "********** Peephole **********\n"
115
4.31k
           << "********** Function: " << MF.getName() << '\n';
116
4.31k
  });
117
4.31k
118
4.31k
  MachineRegisterInfo &MRI = MF.getRegInfo();
119
4.31k
  WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
120
4.31k
  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
121
4.31k
  const WebAssemblyTargetLowering &TLI =
122
4.31k
      *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
123
4.31k
  auto &LibInfo = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
124
4.31k
  bool Changed = false;
125
4.31k
126
4.31k
  for (auto &MBB : MF)
127
4.98k
    for (auto &MI : MBB)
128
54.8k
      switch (MI.getOpcode()) {
129
54.8k
      default:
130
50.2k
        break;
131
54.8k
      case WebAssembly::CALL_i32:
132
269
      case WebAssembly::CALL_i64: {
133
269
        MachineOperand &Op1 = MI.getOperand(1);
134
269
        if (Op1.isSymbol()) {
135
36
          StringRef Name(Op1.getSymbolName());
136
36
          if (Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
137
36
              
Name == TLI.getLibcallName(RTLIB::MEMMOVE)26
||
138
36
              
Name == TLI.getLibcallName(RTLIB::MEMSET)21
) {
139
24
            LibFunc Func;
140
24
            if (LibInfo.getLibFunc(Name, Func)) {
141
24
              const auto &Op2 = MI.getOperand(2);
142
24
              if (!Op2.isReg())
143
0
                report_fatal_error("Peephole: call to builtin function with "
144
0
                                   "wrong signature, not consuming reg");
145
24
              MachineOperand &MO = MI.getOperand(0);
146
24
              unsigned OldReg = MO.getReg();
147
24
              unsigned NewReg = Op2.getReg();
148
24
149
24
              if (MRI.getRegClass(NewReg) != MRI.getRegClass(OldReg))
150
0
                report_fatal_error("Peephole: call to builtin function with "
151
0
                                   "wrong signature, from/to mismatch");
152
24
              Changed |= maybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI);
153
24
            }
154
24
          }
155
36
        }
156
269
        break;
157
269
      }
158
269
      // Optimize away an explicit void return at the end of the function.
159
1.09k
      case WebAssembly::RETURN_I32:
160
1.09k
        Changed |= maybeRewriteToFallthrough(
161
1.09k
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I32,
162
1.09k
            WebAssembly::COPY_I32);
163
1.09k
        break;
164
331
      case WebAssembly::RETURN_I64:
165
331
        Changed |= maybeRewriteToFallthrough(
166
331
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I64,
167
331
            WebAssembly::COPY_I64);
168
331
        break;
169
269
      case WebAssembly::RETURN_F32:
170
78
        Changed |= maybeRewriteToFallthrough(
171
78
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F32,
172
78
            WebAssembly::COPY_F32);
173
78
        break;
174
269
      case WebAssembly::RETURN_F64:
175
68
        Changed |= maybeRewriteToFallthrough(
176
68
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F64,
177
68
            WebAssembly::COPY_F64);
178
68
        break;
179
269
      case WebAssembly::RETURN_v16i8:
180
207
        Changed |= maybeRewriteToFallthrough(
181
207
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v16i8,
182
207
            WebAssembly::COPY_V128);
183
207
        break;
184
269
      case WebAssembly::RETURN_v8i16:
185
201
        Changed |= maybeRewriteToFallthrough(
186
201
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v8i16,
187
201
            WebAssembly::COPY_V128);
188
201
        break;
189
316
      case WebAssembly::RETURN_v4i32:
190
316
        Changed |= maybeRewriteToFallthrough(
191
316
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4i32,
192
316
            WebAssembly::COPY_V128);
193
316
        break;
194
269
      case WebAssembly::RETURN_v2i64:
195
183
        Changed |= maybeRewriteToFallthrough(
196
183
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2i64,
197
183
            WebAssembly::COPY_V128);
198
183
        break;
199
269
      case WebAssembly::RETURN_v4f32:
200
165
        Changed |= maybeRewriteToFallthrough(
201
165
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4f32,
202
165
            WebAssembly::COPY_V128);
203
165
        break;
204
269
      case WebAssembly::RETURN_v2f64:
205
98
        Changed |= maybeRewriteToFallthrough(
206
98
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2f64,
207
98
            WebAssembly::COPY_V128);
208
98
        break;
209
1.56k
      case WebAssembly::RETURN_VOID:
210
1.56k
        Changed |= maybeRewriteToFallthrough(
211
1.56k
            MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_VOID,
212
1.56k
            WebAssembly::INSTRUCTION_LIST_END);
213
1.56k
        break;
214
54.8k
      }
215
4.31k
216
4.31k
  return Changed;
217
4.31k
}