LLVM  4.0.0
WebAssemblyPeephole.cpp
Go to the documentation of this file.
1 //===-- 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 
16 #include "WebAssembly.h"
18 #include "WebAssemblySubtarget.h"
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "wasm-peephole"
26 
28  "disable-wasm-fallthrough-return-opt", cl::Hidden,
29  cl::desc("WebAssembly: Disable fallthrough-return optimizations."),
30  cl::init(false));
31 
32 namespace {
33 class WebAssemblyPeephole final : public MachineFunctionPass {
34  StringRef getPassName() const override {
35  return "WebAssembly late peephole optimizer";
36  }
37 
38  void getAnalysisUsage(AnalysisUsage &AU) const override {
39  AU.setPreservesCFG();
42  }
43 
44  bool runOnMachineFunction(MachineFunction &MF) override;
45 
46 public:
47  static char ID;
48  WebAssemblyPeephole() : MachineFunctionPass(ID) {}
49 };
50 } // end anonymous namespace
51 
54  return new WebAssemblyPeephole();
55 }
56 
57 /// If desirable, rewrite NewReg to a drop register.
58 static bool MaybeRewriteToDrop(unsigned OldReg, unsigned NewReg,
61  bool Changed = false;
62  if (OldReg == NewReg) {
63  Changed = true;
64  unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg));
65  MO.setReg(NewReg);
66  MO.setIsDead();
67  MFI.stackifyVReg(NewReg);
68  }
69  return Changed;
70 }
71 
73  const MachineFunction &MF,
77  unsigned FallthroughOpc,
78  unsigned CopyLocalOpc) {
80  return false;
81  if (&MBB != &MF.back())
82  return false;
83  if (&MI != &MBB.back())
84  return false;
85 
86  // If the operand isn't stackified, insert a COPY to read the operand and
87  // stackify it.
88  MachineOperand &MO = MI.getOperand(0);
89  unsigned Reg = MO.getReg();
90  if (!MFI.isVRegStackified(Reg)) {
91  unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(Reg));
92  BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(CopyLocalOpc), NewReg)
93  .addReg(Reg);
94  MO.setReg(NewReg);
95  MFI.stackifyVReg(NewReg);
96  }
97 
98  // Rewrite the return.
99  MI.setDesc(TII.get(FallthroughOpc));
100  return true;
101 }
102 
103 bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
104  DEBUG({
105  dbgs() << "********** Peephole **********\n"
106  << "********** Function: " << MF.getName() << '\n';
107  });
108 
111  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
112  const WebAssemblyTargetLowering &TLI =
113  *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
114  auto &LibInfo = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
115  bool Changed = false;
116 
117  for (auto &MBB : MF)
118  for (auto &MI : MBB)
119  switch (MI.getOpcode()) {
120  default:
121  break;
122  case WebAssembly::CALL_I32:
123  case WebAssembly::CALL_I64: {
124  MachineOperand &Op1 = MI.getOperand(1);
125  if (Op1.isSymbol()) {
127  if (Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
131  if (LibInfo.getLibFunc(Name, Func)) {
132  const auto &Op2 = MI.getOperand(2);
133  if (!Op2.isReg())
134  report_fatal_error("Peephole: call to builtin function with "
135  "wrong signature, not consuming reg");
136  MachineOperand &MO = MI.getOperand(0);
137  unsigned OldReg = MO.getReg();
138  unsigned NewReg = Op2.getReg();
139 
140  if (MRI.getRegClass(NewReg) != MRI.getRegClass(OldReg))
141  report_fatal_error("Peephole: call to builtin function with "
142  "wrong signature, from/to mismatch");
143  Changed |= MaybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI);
144  }
145  }
146  }
147  break;
148  }
149  // Optimize away an explicit void return at the end of the function.
150  case WebAssembly::RETURN_I32:
151  Changed |= MaybeRewriteToFallthrough(
152  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I32,
153  WebAssembly::COPY_I32);
154  break;
155  case WebAssembly::RETURN_I64:
156  Changed |= MaybeRewriteToFallthrough(
157  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I64,
158  WebAssembly::COPY_I64);
159  break;
160  case WebAssembly::RETURN_F32:
161  Changed |= MaybeRewriteToFallthrough(
162  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F32,
163  WebAssembly::COPY_F32);
164  break;
165  case WebAssembly::RETURN_F64:
166  Changed |= MaybeRewriteToFallthrough(
167  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F64,
168  WebAssembly::COPY_F64);
169  break;
170  case WebAssembly::RETURN_v16i8:
171  Changed |= MaybeRewriteToFallthrough(
172  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v16i8,
173  WebAssembly::COPY_V128);
174  break;
175  case WebAssembly::RETURN_v8i16:
176  Changed |= MaybeRewriteToFallthrough(
177  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v8i16,
178  WebAssembly::COPY_V128);
179  break;
180  case WebAssembly::RETURN_v4i32:
181  Changed |= MaybeRewriteToFallthrough(
182  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4i32,
183  WebAssembly::COPY_V128);
184  break;
185  case WebAssembly::RETURN_v4f32:
186  Changed |= MaybeRewriteToFallthrough(
187  MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4f32,
188  WebAssembly::COPY_V128);
189  break;
190  case WebAssembly::RETURN_VOID:
192  &MBB == &MF.back() && &MI == &MBB.back())
193  MI.setDesc(TII.get(WebAssembly::FALLTHROUGH_RETURN_VOID));
194  break;
195  }
196 
197  return Changed;
198 }
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
unsigned createVirtualRegister(const TargetRegisterClass *RegClass)
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static cl::opt< bool > DisableWebAssemblyFallthroughReturnOpt("disable-wasm-fallthrough-return-opt", cl::Hidden, cl::desc("WebAssembly: Disable fallthrough-return optimizations."), cl::init(false))
const char * getSymbolName() const
bool isVRegStackified(unsigned VReg) const
void setIsDead(bool Val=true)
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
AnalysisUsage & addRequired()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
Reg
All possible values of the reg field in the ModR/M byte.
MachineBasicBlock * MBB
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:395
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:279
This file provides WebAssembly-specific target descriptions.
Represent the analysis usage information of a pass.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
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:298
static bool MaybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB, const MachineFunction &MF, WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI, const WebAssemblyInstrInfo &TII, unsigned FallthroughOpc, unsigned CopyLocalOpc)
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...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
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:276
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:250
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
FunctionPass * createWebAssemblyPeephole()
Representation of each machine instruction.
Definition: MachineInstr.h:52
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
void setReg(unsigned Reg)
Change the register this operand corresponds to.
This file declares WebAssembly-specific per-machine-function information.
static bool MaybeRewriteToDrop(unsigned OldReg, unsigned NewReg, MachineOperand &MO, WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI)
If desirable, rewrite NewReg to a drop register.
unsigned getReg() const
getReg - Returns the register number.
#define DEBUG(X)
Definition: Debug.h:100
const MachineBasicBlock & back() const
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
StringRef getName() const
getName - Return the name of the corresponding LLVM function.