blob: ade29f7febbb2fce78cba3b24479ba8ce89321c1 [file] [log] [blame]
Dan Gohman81719f82015-11-25 16:55:01 +00001//===-- WebAssemblyPeephole.cpp - WebAssembly Peephole Optimiztions -------===//
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/// \file
11/// \brief Late peephole optimizations for WebAssembly.
12///
13//===----------------------------------------------------------------------===//
14
15#include "WebAssembly.h"
16#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17#include "WebAssemblyMachineFunctionInfo.h"
Dan Gohmanbdf08d52016-01-26 04:01:11 +000018#include "WebAssemblySubtarget.h"
19#include "llvm/Analysis/TargetLibraryInfo.h"
Dan Gohman81719f82015-11-25 16:55:01 +000020#include "llvm/CodeGen/MachineFunctionPass.h"
Dan Gohmanbdf08d52016-01-26 04:01:11 +000021#include "llvm/CodeGen/MachineRegisterInfo.h"
Dan Gohman81719f82015-11-25 16:55:01 +000022using namespace llvm;
23
24#define DEBUG_TYPE "wasm-peephole"
25
26namespace {
27class WebAssemblyPeephole final : public MachineFunctionPass {
28 const char *getPassName() const override {
29 return "WebAssembly late peephole optimizer";
30 }
31
Dan Gohmanacc09412015-12-10 14:12:04 +000032 void getAnalysisUsage(AnalysisUsage &AU) const override {
33 AU.setPreservesCFG();
Dan Gohmanbdf08d52016-01-26 04:01:11 +000034 AU.addRequired<TargetLibraryInfoWrapperPass>();
Dan Gohmanacc09412015-12-10 14:12:04 +000035 MachineFunctionPass::getAnalysisUsage(AU);
36 }
37
Dan Gohman81719f82015-11-25 16:55:01 +000038 bool runOnMachineFunction(MachineFunction &MF) override;
39
40public:
41 static char ID;
42 WebAssemblyPeephole() : MachineFunctionPass(ID) {}
43};
44} // end anonymous namespace
45
46char WebAssemblyPeephole::ID = 0;
47FunctionPass *llvm::createWebAssemblyPeephole() {
48 return new WebAssemblyPeephole();
49}
50
Dan Gohman27a11eef2016-02-21 03:27:22 +000051static const TargetRegisterClass *GetRegClass(const MachineRegisterInfo &MRI,
52 unsigned RegNo) {
53 return TargetRegisterInfo::isVirtualRegister(RegNo)
54 ? MRI.getRegClass(RegNo)
55 : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(RegNo);
56}
57
Dan Gohman71008092016-05-17 23:19:03 +000058/// If desirable, rewrite NewReg to a drop register.
59static bool MaybeRewriteToDrop(unsigned OldReg, unsigned NewReg,
60 MachineOperand &MO,
61 WebAssemblyFunctionInfo &MFI,
62 MachineRegisterInfo &MRI) {
Dan Gohman81719f82015-11-25 16:55:01 +000063 bool Changed = false;
Dan Gohman27a11eef2016-02-21 03:27:22 +000064 if (OldReg == NewReg) {
Dan Gohmanbdf08d52016-01-26 04:01:11 +000065 Changed = true;
Dan Gohman27a11eef2016-02-21 03:27:22 +000066 unsigned NewReg = MRI.createVirtualRegister(GetRegClass(MRI, OldReg));
Dan Gohmanbdf08d52016-01-26 04:01:11 +000067 MO.setReg(NewReg);
68 MO.setIsDead();
69 MFI.stackifyVReg(NewReg);
70 MFI.addWAReg(NewReg, WebAssemblyFunctionInfo::UnusedReg);
71 }
72 return Changed;
73}
74
75bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
76 DEBUG({
77 dbgs() << "********** Store Results **********\n"
78 << "********** Function: " << MF.getName() << '\n';
79 });
Dan Gohman81719f82015-11-25 16:55:01 +000080
81 MachineRegisterInfo &MRI = MF.getRegInfo();
82 WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
Dan Gohmanbdf08d52016-01-26 04:01:11 +000083 const WebAssemblyTargetLowering &TLI =
84 *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
85 auto &LibInfo = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
86 bool Changed = false;
Dan Gohman81719f82015-11-25 16:55:01 +000087
88 for (auto &MBB : MF)
89 for (auto &MI : MBB)
90 switch (MI.getOpcode()) {
91 default:
92 break;
93 case WebAssembly::STORE8_I32:
94 case WebAssembly::STORE16_I32:
95 case WebAssembly::STORE8_I64:
96 case WebAssembly::STORE16_I64:
97 case WebAssembly::STORE32_I64:
98 case WebAssembly::STORE_F32:
99 case WebAssembly::STORE_F64:
100 case WebAssembly::STORE_I32:
101 case WebAssembly::STORE_I64: {
102 // Store instructions return their value operand. If we ended up using
103 // the same register for both, replace it with a dead def so that it
Dan Gohman71008092016-05-17 23:19:03 +0000104 // can use $drop instead.
Dan Gohman81719f82015-11-25 16:55:01 +0000105 MachineOperand &MO = MI.getOperand(0);
106 unsigned OldReg = MO.getReg();
Dan Gohmanbdf08d52016-01-26 04:01:11 +0000107 unsigned NewReg =
108 MI.getOperand(WebAssembly::StoreValueOperandNo).getReg();
Dan Gohman71008092016-05-17 23:19:03 +0000109 Changed |= MaybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI);
Dan Gohmanbdf08d52016-01-26 04:01:11 +0000110 break;
111 }
112 case WebAssembly::CALL_I32:
113 case WebAssembly::CALL_I64: {
114 MachineOperand &Op1 = MI.getOperand(1);
115 if (Op1.isSymbol()) {
116 StringRef Name(Op1.getSymbolName());
117 if (Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
118 Name == TLI.getLibcallName(RTLIB::MEMMOVE) ||
119 Name == TLI.getLibcallName(RTLIB::MEMSET)) {
120 LibFunc::Func Func;
121 if (LibInfo.getLibFunc(Name, Func)) {
JF Bastien1a6c7602016-01-26 20:22:42 +0000122 const auto &Op2 = MI.getOperand(2);
Derek Schuffe7305cc2016-01-26 21:08:27 +0000123 if (!Op2.isReg())
JF Bastien1a6c7602016-01-26 20:22:42 +0000124 report_fatal_error("Peephole: call to builtin function with "
Derek Schuffe7305cc2016-01-26 21:08:27 +0000125 "wrong signature, not consuming reg");
126 MachineOperand &MO = MI.getOperand(0);
127 unsigned OldReg = MO.getReg();
128 unsigned NewReg = Op2.getReg();
Derek Schuff90d9e8d2016-01-26 22:47:43 +0000129
Dan Gohman27a11eef2016-02-21 03:27:22 +0000130 if (GetRegClass(MRI, NewReg) != GetRegClass(MRI, OldReg))
Derek Schuffe7305cc2016-01-26 21:08:27 +0000131 report_fatal_error("Peephole: call to builtin function with "
132 "wrong signature, from/to mismatch");
Dan Gohman71008092016-05-17 23:19:03 +0000133 Changed |= MaybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI);
Dan Gohmanbdf08d52016-01-26 04:01:11 +0000134 }
135 }
Dan Gohman81719f82015-11-25 16:55:01 +0000136 }
137 }
138 }
139
140 return Changed;
141}