LLVM  10.0.0svn
WebAssemblyPeephole.cpp
Go to the documentation of this file.
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 
15 #include "WebAssembly.h"
17 #include "WebAssemblySubtarget.h"
22 using namespace llvm;
23 
24 #define DEBUG_TYPE "wasm-peephole"
25 
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  StringRef getPassName() const override {
34  return "WebAssembly late peephole optimizer";
35  }
36 
37  void getAnalysisUsage(AnalysisUsage &AU) const override {
38  AU.setPreservesCFG();
41  }
42 
43  bool runOnMachineFunction(MachineFunction &MF) override;
44 
45 public:
46  static char ID;
47  WebAssemblyPeephole() : MachineFunctionPass(ID) {}
48 };
49 } // end anonymous namespace
50 
52 INITIALIZE_PASS(WebAssemblyPeephole, DEBUG_TYPE,
53  "WebAssembly peephole optimizations", false, false)
54 
56  return new WebAssemblyPeephole();
57 }
58 
59 /// If desirable, rewrite NewReg to a drop register.
60 static bool maybeRewriteToDrop(unsigned OldReg, unsigned NewReg,
63  bool Changed = false;
64  if (OldReg == NewReg) {
65  Changed = true;
66  Register NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg));
67  MO.setReg(NewReg);
68  MO.setIsDead();
69  MFI.stackifyVReg(NewReg);
70  }
71  return Changed;
72 }
73 
75  const MachineFunction &MF,
78  const WebAssemblyInstrInfo &TII) {
80  return false;
81  if (&MBB != &MF.back())
82  return false;
83 
84  MachineBasicBlock::iterator End = MBB.end();
85  --End;
86  assert(End->getOpcode() == WebAssembly::END_FUNCTION);
87  --End;
88  if (&MI != &*End)
89  return false;
90 
91  for (auto &MO : MI.explicit_operands()) {
92  // If the operand isn't stackified, insert a COPY to read the operands and
93  // stackify them.
94  Register Reg = MO.getReg();
95  if (!MFI.isVRegStackified(Reg)) {
96  unsigned CopyLocalOpc;
97  const TargetRegisterClass *RegClass = MRI.getRegClass(Reg);
98  switch (RegClass->getID()) {
99  case WebAssembly::I32RegClassID:
100  CopyLocalOpc = WebAssembly::COPY_I32;
101  break;
102  case WebAssembly::I64RegClassID:
103  CopyLocalOpc = WebAssembly::COPY_I64;
104  break;
105  case WebAssembly::F32RegClassID:
106  CopyLocalOpc = WebAssembly::COPY_F32;
107  break;
108  case WebAssembly::F64RegClassID:
109  CopyLocalOpc = WebAssembly::COPY_F64;
110  break;
111  case WebAssembly::V128RegClassID:
112  CopyLocalOpc = WebAssembly::COPY_V128;
113  break;
114  case WebAssembly::EXNREFRegClassID:
115  CopyLocalOpc = WebAssembly::COPY_EXNREF;
116  break;
117  default:
118  llvm_unreachable("Unexpected register class for return operand");
119  }
120  Register NewReg = MRI.createVirtualRegister(RegClass);
121  BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(CopyLocalOpc), NewReg)
122  .addReg(Reg);
123  MO.setReg(NewReg);
124  MFI.stackifyVReg(NewReg);
125  }
126  }
127 
128  MI.setDesc(TII.get(WebAssembly::FALLTHROUGH_RETURN));
129  return true;
130 }
131 
132 bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
133  LLVM_DEBUG({
134  dbgs() << "********** Peephole **********\n"
135  << "********** Function: " << MF.getName() << '\n';
136  });
137 
140  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
141  const WebAssemblyTargetLowering &TLI =
142  *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
143  auto &LibInfo =
144  getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(MF.getFunction());
145  bool Changed = false;
146 
147  for (auto &MBB : MF)
148  for (auto &MI : MBB)
149  switch (MI.getOpcode()) {
150  default:
151  break;
152  case WebAssembly::CALL_i32:
153  case WebAssembly::CALL_i64: {
154  MachineOperand &Op1 = MI.getOperand(1);
155  if (Op1.isSymbol()) {
157  if (Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
158  Name == TLI.getLibcallName(RTLIB::MEMMOVE) ||
159  Name == TLI.getLibcallName(RTLIB::MEMSET)) {
160  LibFunc Func;
161  if (LibInfo.getLibFunc(Name, Func)) {
162  const auto &Op2 = MI.getOperand(2);
163  if (!Op2.isReg())
164  report_fatal_error("Peephole: call to builtin function with "
165  "wrong signature, not consuming reg");
166  MachineOperand &MO = MI.getOperand(0);
167  Register OldReg = MO.getReg();
168  Register NewReg = Op2.getReg();
169 
170  if (MRI.getRegClass(NewReg) != MRI.getRegClass(OldReg))
171  report_fatal_error("Peephole: call to builtin function with "
172  "wrong signature, from/to mismatch");
173  Changed |= maybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI);
174  }
175  }
176  }
177  break;
178  }
179  // Optimize away an explicit void return at the end of the function.
180  case WebAssembly::RETURN:
181  Changed |= maybeRewriteToFallthrough(MI, MBB, MF, MFI, MRI, TII);
182  break;
183  }
184 
185  return Changed;
186 }
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
iterator_range< mop_iterator > explicit_operands()
Definition: MachineInstr.h:482
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:384
FunctionPass * createWebAssemblyPeephole()
unsigned Reg
static cl::opt< bool > DisableWebAssemblyFallthroughReturnOpt("disable-wasm-fallthrough-return-opt", cl::Hidden, cl::desc("WebAssembly: Disable fallthrough-return optimizations."), cl::init(false))
void setIsDead(bool Val=true)
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static bool maybeRewriteToDrop(unsigned OldReg, unsigned NewReg, MachineOperand &MO, WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI)
If desirable, rewrite NewReg to a drop register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
const char * getSymbolName() const
unsigned getID() const
Return the register class ID number.
void setReg(Register Reg)
Change the register this operand corresponds to.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
This file provides WebAssembly-specific target descriptions.
Represent the analysis usage information of a pass.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
MachineOperand class - Representation of each machine instruction operand.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:301
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
static bool maybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB, const MachineFunction &MF, WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI, const WebAssemblyInstrInfo &TII)
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:63
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
This file declares WebAssembly-specific per-machine-function information.
const MachineBasicBlock & back() const
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
INITIALIZE_PASS(WebAssemblyPeephole, DEBUG_TYPE, "WebAssembly peephole optimizations", false, false) FunctionPass *llvm
Register getReg() const
getReg - Returns the register number.
#define LLVM_DEBUG(X)
Definition: Debug.h:122
#define DEBUG_TYPE
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.