LLVM  10.0.0svn
WebAssemblyMemIntrinsicResults.cpp
Go to the documentation of this file.
1 //== WebAssemblyMemIntrinsicResults.cpp - Optimize memory intrinsic results ==//
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 /// This file implements an optimization pass using memory intrinsic results.
11 ///
12 /// Calls to memory intrinsics (memcpy, memmove, memset) return the destination
13 /// address. They are in the form of
14 /// %dst_new = call @memcpy %dst, %src, %len
15 /// where %dst and %dst_new registers contain the same value.
16 ///
17 /// This is to enable an optimization wherein uses of the %dst register used in
18 /// the parameter can be replaced by uses of the %dst_new register used in the
19 /// result, making the %dst register more likely to be single-use, thus more
20 /// likely to be useful to register stackifying, and potentially also exposing
21 /// the call instruction itself to register stackifying. These both can reduce
22 /// local.get/local.set traffic.
23 ///
24 /// The LLVM intrinsics for these return void so they can't use the returned
25 /// attribute and consequently aren't handled by the OptimizeReturned pass.
26 ///
27 //===----------------------------------------------------------------------===//
28 
30 #include "WebAssembly.h"
32 #include "WebAssemblySubtarget.h"
38 #include "llvm/CodeGen/Passes.h"
39 #include "llvm/Support/Debug.h"
41 using namespace llvm;
42 
43 #define DEBUG_TYPE "wasm-mem-intrinsic-results"
44 
45 namespace {
46 class WebAssemblyMemIntrinsicResults final : public MachineFunctionPass {
47 public:
48  static char ID; // Pass identification, replacement for typeid
49  WebAssemblyMemIntrinsicResults() : MachineFunctionPass(ID) {}
50 
51  StringRef getPassName() const override {
52  return "WebAssembly Memory Intrinsic Results";
53  }
54 
55  void getAnalysisUsage(AnalysisUsage &AU) const override {
56  AU.setPreservesCFG();
66  }
67 
68  bool runOnMachineFunction(MachineFunction &MF) override;
69 
70 private:
71 };
72 } // end anonymous namespace
73 
75 INITIALIZE_PASS(WebAssemblyMemIntrinsicResults, DEBUG_TYPE,
76  "Optimize memory intrinsic result values for WebAssembly",
77  false, false)
78 
80  return new WebAssemblyMemIntrinsicResults();
81 }
82 
83 // Replace uses of FromReg with ToReg if they are dominated by MI.
85  unsigned FromReg, unsigned ToReg,
86  const MachineRegisterInfo &MRI,
88  LiveIntervals &LIS) {
89  bool Changed = false;
90 
91  LiveInterval *FromLI = &LIS.getInterval(FromReg);
92  LiveInterval *ToLI = &LIS.getInterval(ToReg);
93 
94  SlotIndex FromIdx = LIS.getInstructionIndex(MI).getRegSlot();
95  VNInfo *FromVNI = FromLI->getVNInfoAt(FromIdx);
96 
98 
99  for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end();
100  I != E;) {
101  MachineOperand &O = *I++;
102  MachineInstr *Where = O.getParent();
103 
104  // Check that MI dominates the instruction in the normal way.
105  if (&MI == Where || !MDT.dominates(&MI, Where))
106  continue;
107 
108  // If this use gets a different value, skip it.
109  SlotIndex WhereIdx = LIS.getInstructionIndex(*Where);
110  VNInfo *WhereVNI = FromLI->getVNInfoAt(WhereIdx);
111  if (WhereVNI && WhereVNI != FromVNI)
112  continue;
113 
114  // Make sure ToReg isn't clobbered before it gets there.
115  VNInfo *ToVNI = ToLI->getVNInfoAt(WhereIdx);
116  if (ToVNI && ToVNI != FromVNI)
117  continue;
118 
119  Changed = true;
120  LLVM_DEBUG(dbgs() << "Setting operand " << O << " in " << *Where << " from "
121  << MI << "\n");
122  O.setReg(ToReg);
123 
124  // If the store's def was previously dead, it is no longer.
125  if (!O.isUndef()) {
126  MI.getOperand(0).setIsDead(false);
127 
128  Indices.push_back(WhereIdx.getRegSlot());
129  }
130  }
131 
132  if (Changed) {
133  // Extend ToReg's liveness.
134  LIS.extendToIndices(*ToLI, Indices);
135 
136  // Shrink FromReg's liveness.
137  LIS.shrinkToUses(FromLI);
138 
139  // If we replaced all dominated uses, FromReg is now killed at MI.
140  if (!FromLI->liveAt(FromIdx.getDeadSlot()))
141  MI.addRegisterKilled(FromReg, MBB.getParent()
143  .getRegisterInfo());
144  }
145 
146  return Changed;
147 }
148 
150  const MachineRegisterInfo &MRI,
152  const WebAssemblyTargetLowering &TLI,
153  const TargetLibraryInfo &LibInfo) {
154  MachineOperand &Op1 = MI.getOperand(1);
155  if (!Op1.isSymbol())
156  return false;
157 
159  bool CallReturnsInput = Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
160  Name == TLI.getLibcallName(RTLIB::MEMMOVE) ||
161  Name == TLI.getLibcallName(RTLIB::MEMSET);
162  if (!CallReturnsInput)
163  return false;
164 
165  LibFunc Func;
166  if (!LibInfo.getLibFunc(Name, Func))
167  return false;
168 
169  Register FromReg = MI.getOperand(2).getReg();
170  Register ToReg = MI.getOperand(0).getReg();
171  if (MRI.getRegClass(FromReg) != MRI.getRegClass(ToReg))
172  report_fatal_error("Memory Intrinsic results: call to builtin function "
173  "with wrong signature, from/to mismatch");
174  return replaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
175 }
176 
177 bool WebAssemblyMemIntrinsicResults::runOnMachineFunction(MachineFunction &MF) {
178  LLVM_DEBUG({
179  dbgs() << "********** Memory Intrinsic Results **********\n"
180  << "********** Function: " << MF.getName() << '\n';
181  });
182 
184  auto &MDT = getAnalysis<MachineDominatorTree>();
185  const WebAssemblyTargetLowering &TLI =
186  *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
187  const auto &LibInfo =
188  getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(MF.getFunction());
189  auto &LIS = getAnalysis<LiveIntervals>();
190  bool Changed = false;
191 
192  // We don't preserve SSA form.
193  MRI.leaveSSA();
194 
195  assert(MRI.tracksLiveness() &&
196  "MemIntrinsicResults expects liveness tracking");
197 
198  for (auto &MBB : MF) {
199  LLVM_DEBUG(dbgs() << "Basic Block: " << MBB.getName() << '\n');
200  for (auto &MI : MBB)
201  switch (MI.getOpcode()) {
202  default:
203  break;
204  case WebAssembly::CALL_i32:
205  case WebAssembly::CALL_i64:
206  Changed |= optimizeCall(MBB, MI, MRI, MDT, LIS, TLI, LibInfo);
207  break;
208  }
209  }
210 
211  return Changed;
212 }
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
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
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:679
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
void setIsDead(bool Val=true)
INITIALIZE_PASS(WebAssemblyMemIntrinsicResults, DEBUG_TYPE, "Optimize memory intrinsic result values for WebAssembly", false, false) FunctionPass *llvm
VNInfo - Value Number Information.
Definition: LiveInterval.h:52
use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static use_nodbg_iterator use_nodbg_end()
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
AnalysisUsage & addRequired()
SlotIndex getDeadSlot() const
Returns the dead def kill slot for the current instruction.
Definition: SlotIndexes.h:259
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const char * getSymbolName() const
void extendToIndices(LiveRange &LR, ArrayRef< SlotIndex > Indices, ArrayRef< SlotIndex > Undefs)
Extend the live range LR to reach all points in Indices.
SlotIndexes pass.
Definition: SlotIndexes.h:314
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
Definition: SlotIndexes.h:254
bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
void setReg(Register Reg)
Change the register this operand corresponds to.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
Definition: LiveInterval.h:412
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.
bool liveAt(SlotIndex index) const
Definition: LiveInterval.h:392
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides WebAssembly-specific target descriptions.
Represent the analysis usage information of a pass.
bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr *> *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
LiveInterval & getInterval(Register Reg)
This file declares the WebAssembly-specific subclass of TargetSubtarget.
MachineOperand class - Representation of each machine instruction operand.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
Provides information about what library functions are available for the current target.
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.
static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS, const WebAssemblyTargetLowering &TLI, const TargetLibraryInfo &LibInfo)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
FunctionPass * createWebAssemblyMemIntrinsicResults()
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
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
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares WebAssembly-specific per-machine-function information.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
static bool replaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI, unsigned FromReg, unsigned ToReg, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS)
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
Register getReg() const
getReg - Returns the register number.
#define LLVM_DEBUG(X)
Definition: Debug.h:122
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:415
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:83
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.