LLVM  4.0.0
WebAssemblyStoreResults.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyStoreResults.cpp - Optimize using store result values --===//
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 This file implements an optimization pass using store result values.
12 ///
13 /// WebAssembly's store instructions return the stored value. This is to enable
14 /// an optimization wherein uses of the stored value can be replaced by uses of
15 /// the store's result value, making the stored value register more likely to
16 /// be single-use, thus more likely to be useful to register stackifying, and
17 /// potentially also exposing the store to register stackifying. These both can
18 /// reduce get_local/set_local traffic.
19 ///
20 /// This pass also performs this optimization for memcpy, memmove, and memset
21 /// calls, since the LLVM intrinsics for these return void so they can't use the
22 /// returned attribute and consequently aren't handled by the OptimizeReturned
23 /// pass.
24 ///
25 //===----------------------------------------------------------------------===//
26 
27 #include "WebAssembly.h"
30 #include "WebAssemblySubtarget.h"
36 #include "llvm/CodeGen/Passes.h"
37 #include "llvm/Support/Debug.h"
39 using namespace llvm;
40 
41 #define DEBUG_TYPE "wasm-store-results"
42 
43 namespace {
44 class WebAssemblyStoreResults final : public MachineFunctionPass {
45 public:
46  static char ID; // Pass identification, replacement for typeid
47  WebAssemblyStoreResults() : MachineFunctionPass(ID) {}
48 
49  StringRef getPassName() const override { return "WebAssembly Store Results"; }
50 
51  void getAnalysisUsage(AnalysisUsage &AU) const override {
52  AU.setPreservesCFG();
62  }
63 
64  bool runOnMachineFunction(MachineFunction &MF) override;
65 
66 private:
67 };
68 } // end anonymous namespace
69 
72  return new WebAssemblyStoreResults();
73 }
74 
75 // Replace uses of FromReg with ToReg if they are dominated by MI.
77  unsigned FromReg, unsigned ToReg,
78  const MachineRegisterInfo &MRI,
80  LiveIntervals &LIS) {
81  bool Changed = false;
82 
83  LiveInterval *FromLI = &LIS.getInterval(FromReg);
84  LiveInterval *ToLI = &LIS.getInterval(ToReg);
85 
86  SlotIndex FromIdx = LIS.getInstructionIndex(MI).getRegSlot();
87  VNInfo *FromVNI = FromLI->getVNInfoAt(FromIdx);
88 
90 
91  for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end(); I != E;) {
92  MachineOperand &O = *I++;
93  MachineInstr *Where = O.getParent();
94 
95  // Check that MI dominates the instruction in the normal way.
96  if (&MI == Where || !MDT.dominates(&MI, Where))
97  continue;
98 
99  // If this use gets a different value, skip it.
100  SlotIndex WhereIdx = LIS.getInstructionIndex(*Where);
101  VNInfo *WhereVNI = FromLI->getVNInfoAt(WhereIdx);
102  if (WhereVNI && WhereVNI != FromVNI)
103  continue;
104 
105  // Make sure ToReg isn't clobbered before it gets there.
106  VNInfo *ToVNI = ToLI->getVNInfoAt(WhereIdx);
107  if (ToVNI && ToVNI != FromVNI)
108  continue;
109 
110  Changed = true;
111  DEBUG(dbgs() << "Setting operand " << O << " in " << *Where << " from "
112  << MI << "\n");
113  O.setReg(ToReg);
114 
115  // If the store's def was previously dead, it is no longer.
116  if (!O.isUndef()) {
117  MI.getOperand(0).setIsDead(false);
118 
119  Indices.push_back(WhereIdx.getRegSlot());
120  }
121  }
122 
123  if (Changed) {
124  // Extend ToReg's liveness.
125  LIS.extendToIndices(*ToLI, Indices);
126 
127  // Shrink FromReg's liveness.
128  LIS.shrinkToUses(FromLI);
129 
130  // If we replaced all dominated uses, FromReg is now killed at MI.
131  if (!FromLI->liveAt(FromIdx.getDeadSlot()))
132  MI.addRegisterKilled(FromReg,
134  .getRegisterInfo());
135  }
136 
137  return Changed;
138 }
139 
141  const MachineRegisterInfo &MRI,
143  LiveIntervals &LIS,
144  const WebAssemblyTargetLowering &TLI,
145  const TargetLibraryInfo &LibInfo) {
146  MachineOperand &Op1 = MI.getOperand(1);
147  if (!Op1.isSymbol())
148  return false;
149 
151  bool callReturnsInput = Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
154  if (!callReturnsInput)
155  return false;
156 
158  if (!LibInfo.getLibFunc(Name, Func))
159  return false;
160 
161  unsigned FromReg = MI.getOperand(2).getReg();
162  unsigned ToReg = MI.getOperand(0).getReg();
163  if (MRI.getRegClass(FromReg) != MRI.getRegClass(ToReg))
164  report_fatal_error("Store results: call to builtin function with wrong "
165  "signature, from/to mismatch");
166  return ReplaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
167 }
168 
169 bool WebAssemblyStoreResults::runOnMachineFunction(MachineFunction &MF) {
170  DEBUG({
171  dbgs() << "********** Store Results **********\n"
172  << "********** Function: " << MF.getName() << '\n';
173  });
174 
176  MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
177  const WebAssemblyTargetLowering &TLI =
178  *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
179  const auto &LibInfo = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
180  LiveIntervals &LIS = getAnalysis<LiveIntervals>();
181  bool Changed = false;
182 
183  // We don't preserve SSA form.
184  MRI.leaveSSA();
185 
186  assert(MRI.tracksLiveness() && "StoreResults expects liveness tracking");
187 
188  for (auto &MBB : MF) {
189  DEBUG(dbgs() << "Basic Block: " << MBB.getName() << '\n');
190  for (auto &MI : MBB)
191  switch (MI.getOpcode()) {
192  default:
193  break;
194  case WebAssembly::CALL_I32:
195  case WebAssembly::CALL_I64:
196  Changed |= optimizeCall(MBB, MI, MRI, MDT, LIS, TLI, LibInfo);
197  break;
198  }
199  }
200 
201  return Changed;
202 }
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS, const WebAssemblyTargetLowering &TLI, const TargetLibraryInfo &LibInfo)
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:625
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
const char * getSymbolName() const
void setIsDead(bool Val=true)
VNInfo - Value Number Information.
Definition: LiveInterval.h:45
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static use_nodbg_iterator use_nodbg_end()
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
Definition: LiveInterval.h:396
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 TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
bool isUndef() const
SlotIndex getDeadSlot() const
Returns the dead def kill slot for the current instruction.
Definition: SlotIndexes.h:252
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:323
MachineBasicBlock * MBB
bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses...
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const
Searches for a particular function name.
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.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
bool liveAt(SlotIndex index) const
Definition: LiveInterval.h:376
This file declares the WebAssembly-specific subclass of TargetSubtarget.
FunctionPass * createWebAssemblyStoreResults()
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
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:276
LiveInterval & getInterval(unsigned Reg)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
StringRef getName() const
Return the name of the corresponding LLVM basic block, or "(null)".
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:52
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI, unsigned FromReg, unsigned ToReg, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS)
void setReg(unsigned Reg)
Change the register this operand corresponds to.
#define I(x, y, z)
Definition: MD5.cpp:54
This file declares WebAssembly-specific per-machine-function information.
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:247
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define DEBUG(X)
Definition: Debug.h:100
bool addRegisterKilled(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
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.
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:76
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const