LLVM  14.0.0git
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 (MachineOperand &O :
101  MachineInstr *Where = O.getParent();
102 
103  // Check that MI dominates the instruction in the normal way.
104  if (&MI == Where || !MDT.dominates(&MI, Where))
105  continue;
106 
107  // If this use gets a different value, skip it.
108  SlotIndex WhereIdx = LIS.getInstructionIndex(*Where);
109  VNInfo *WhereVNI = FromLI->getVNInfoAt(WhereIdx);
110  if (WhereVNI && WhereVNI != FromVNI)
111  continue;
112 
113  // Make sure ToReg isn't clobbered before it gets there.
114  VNInfo *ToVNI = ToLI->getVNInfoAt(WhereIdx);
115  if (ToVNI && ToVNI != FromVNI)
116  continue;
117 
118  Changed = true;
119  LLVM_DEBUG(dbgs() << "Setting operand " << O << " in " << *Where << " from "
120  << MI << "\n");
121  O.setReg(ToReg);
122 
123  // If the store's def was previously dead, it is no longer.
124  if (!O.isUndef()) {
125  MI.getOperand(0).setIsDead(false);
126 
127  Indices.push_back(WhereIdx.getRegSlot());
128  }
129  }
130 
131  if (Changed) {
132  // Extend ToReg's liveness.
133  LIS.extendToIndices(*ToLI, Indices);
134 
135  // Shrink FromReg's liveness.
136  LIS.shrinkToUses(FromLI);
137 
138  // If we replaced all dominated uses, FromReg is now killed at MI.
139  if (!FromLI->liveAt(FromIdx.getDeadSlot()))
140  MI.addRegisterKilled(FromReg, MBB.getParent()
142  .getRegisterInfo());
143  }
144 
145  return Changed;
146 }
147 
149  const MachineRegisterInfo &MRI,
151  const WebAssemblyTargetLowering &TLI,
152  const TargetLibraryInfo &LibInfo) {
153  MachineOperand &Op1 = MI.getOperand(1);
154  if (!Op1.isSymbol())
155  return false;
156 
158  bool CallReturnsInput = Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
159  Name == TLI.getLibcallName(RTLIB::MEMMOVE) ||
160  Name == TLI.getLibcallName(RTLIB::MEMSET);
161  if (!CallReturnsInput)
162  return false;
163 
164  LibFunc Func;
165  if (!LibInfo.getLibFunc(Name, Func))
166  return false;
167 
168  Register FromReg = MI.getOperand(2).getReg();
169  Register ToReg = MI.getOperand(0).getReg();
170  if (MRI.getRegClass(FromReg) != MRI.getRegClass(ToReg))
171  report_fatal_error("Memory Intrinsic results: call to builtin function "
172  "with wrong signature, from/to mismatch");
173  return replaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
174 }
175 
176 bool WebAssemblyMemIntrinsicResults::runOnMachineFunction(MachineFunction &MF) {
177  LLVM_DEBUG({
178  dbgs() << "********** Memory Intrinsic Results **********\n"
179  << "********** Function: " << MF.getName() << '\n';
180  });
181 
183  auto &MDT = getAnalysis<MachineDominatorTree>();
184  const WebAssemblyTargetLowering &TLI =
185  *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
186  const auto &LibInfo =
187  getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(MF.getFunction());
188  auto &LIS = getAnalysis<LiveIntervals>();
189  bool Changed = false;
190 
191  // We don't preserve SSA form.
192  MRI.leaveSSA();
193 
195  "MemIntrinsicResults expects liveness tracking");
196 
197  for (auto &MBB : MF) {
198  LLVM_DEBUG(dbgs() << "Basic Block: " << MBB.getName() << '\n');
199  for (auto &MI : MBB)
200  switch (MI.getOpcode()) {
201  default:
202  break;
203  case WebAssembly::CALL:
204  Changed |= optimizeCall(MBB, MI, MRI, MDT, LIS, TLI, LibInfo);
205  break;
206  }
207  }
208 
209  return Changed;
210 }
llvm::WebAssemblySubtarget::getRegisterInfo
const WebAssemblyRegisterInfo * getRegisterInfo() const override
Definition: WebAssemblySubtarget.h:81
DEBUG_TYPE
#define DEBUG_TYPE
Definition: WebAssemblyMemIntrinsicResults.cpp:43
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
WebAssembly.h
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition: MachineRegisterInfo.h:52
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::TargetLoweringBase::getLibcallName
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
Definition: TargetLowering.h:2924
llvm::MachineOperand::isSymbol
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
Definition: MachineOperand.h:341
llvm::AArch64ISD::CALL
@ CALL
Definition: AArch64ISelLowering.h:52
llvm::ARMISD::MEMCPY
@ MEMCPY
Definition: ARMISelLowering.h:309
llvm::MachineDominatorTree::dominates
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
Definition: MachineDominators.h:109
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:102
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::LiveIntervals::getInstructionIndex
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
Definition: LiveIntervals.h:226
MachineRegisterInfo.h
llvm::MachineRegisterInfo::tracksLiveness
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
Definition: MachineRegisterInfo.h:197
llvm::WebAssemblyTargetLowering
Definition: WebAssemblyISelLowering.h:43
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:644
llvm::MachineRegisterInfo::use_nodbg_operands
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
Definition: MachineRegisterInfo.h:526
llvm::LiveRange::liveAt
bool liveAt(SlotIndex index) const
Definition: LiveInterval.h:393
llvm::MachineBlockFrequencyInfo
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
Definition: MachineBlockFrequencyInfo.h:33
llvm::LibFunc
LibFunc
Definition: TargetLibraryInfo.h:34
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
TargetLibraryInfo.h
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::TargetLibraryInfo::getLibFunc
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
Definition: TargetLibraryInfo.h:291
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:143
llvm::SlotIndex::getDeadSlot
SlotIndex getDeadSlot() const
Returns the dead def kill slot for the current instruction.
Definition: SlotIndexes.h:259
llvm::SlotIndexes
SlotIndexes pass.
Definition: SlotIndexes.h:314
llvm::LiveInterval
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:680
llvm::SlotIndex
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:83
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
WebAssemblyMCTargetDesc.h
replaceDominatedUses
static bool replaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI, unsigned FromReg, unsigned ToReg, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS)
Definition: WebAssemblyMemIntrinsicResults.cpp:84
llvm::MachineRegisterInfo::getRegClass
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
Definition: MachineRegisterInfo.h:634
Passes.h
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:634
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:206
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
optimizeCall
static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS, const WebAssemblyTargetLowering &TLI, const TargetLibraryInfo &LibInfo)
Definition: WebAssemblyMemIntrinsicResults.cpp:148
llvm::TargetLibraryInfoWrapperPass
Definition: TargetLibraryInfo.h:465
LiveIntervals.h
llvm::make_early_inc_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:593
llvm::createWebAssemblyMemIntrinsicResults
FunctionPass * createWebAssemblyMemIntrinsicResults()
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:542
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineBasicBlock::getParent
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Definition: MachineBasicBlock.h:225
llvm::LiveIntervals::shrinkToUses
bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
Definition: LiveIntervals.cpp:456
WebAssemblyMachineFunctionInfo.h
llvm::SlotIndex::getRegSlot
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
llvm::LiveIntervals::getInterval
LiveInterval & getInterval(Register Reg)
Definition: LiveIntervals.h:114
llvm::MachineFunction
Definition: MachineFunction.h:234
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:253
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition: PassAnalysisSupport.h:98
llvm::WebAssemblySubtarget
Definition: WebAssemblySubtarget.h:35
INITIALIZE_PASS
INITIALIZE_PASS(WebAssemblyMemIntrinsicResults, DEBUG_TYPE, "Optimize memory intrinsic result values for WebAssembly", false, false) FunctionPass *llvm
Definition: WebAssemblyMemIntrinsicResults.cpp:75
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:600
llvm::LiveIntervals::extendToIndices
void extendToIndices(LiveRange &LR, ArrayRef< SlotIndex > Indices, ArrayRef< SlotIndex > Undefs)
Extend the live range LR to reach all points in Indices.
Definition: LiveIntervals.cpp:633
WebAssemblySubtarget.h
llvm::TargetLibraryInfo
Provides information about what library functions are available for the current target.
Definition: TargetLibraryInfo.h:221
llvm::LiveIntervals
Definition: LiveIntervals.h:54
llvm::VNInfo
VNInfo - Value Number Information.
Definition: LiveInterval.h:53
llvm::LiveRange::getVNInfoAt
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
Definition: LiveInterval.h:413
llvm::MachineOperand::getSymbolName
const char * getSymbolName() const
Definition: MachineOperand.h:608
llvm::MachineRegisterInfo::leaveSSA
void leaveSSA()
Definition: MachineRegisterInfo.h:191
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
raw_ostream.h
llvm::MachineDominatorTree
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Definition: MachineDominators.h:46
MachineBlockFrequencyInfo.h
llvm::MachineBasicBlock::getName
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
Definition: MachineBasicBlock.cpp:313
Debug.h
MachineDominators.h
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38